Linux tcp connections limit

Увеличение максимального количества соединений TCP / IP в Linux

Я программирую сервер, и кажется, что мое количество подключений ограничено, поскольку пропускная способность не насыщается, даже если я установил количество подключений как «неограниченное».

Как я могу увеличить или исключить максимальное количество соединений, которые может одновременно открывать мой Ubuntu Linux box? ОС ограничивает это, или это маршрутизатор или провайдер? Или что-то еще?

На максимальное количество соединений влияют определенные ограничения как на стороне клиента, так и на стороне сервера, хотя и немного по-разному.

На стороне клиента: увеличьте диапазон эфермального порта и уменьшите tcp_fin_timeout

Чтобы узнать значения по умолчанию:

Диапазон внешних портов определяет максимальное количество исходящих сокетов, которое хост может создать с определенного IP-адреса. fin_timeout Определяет минимальное время эти розетки будет находиться в TIME_WAIT состоянии (непригодным для использования после того , как используется один раз). Обычные системные настройки по умолчанию:

  • net.ipv4.ip_local_port_range = 32768 61000
  • net.ipv4.tcp_fin_timeout = 60

Это в основном означает, что ваша система не может постоянно гарантировать больше (61000 — 32768) / 60 = 470 сокетов в секунду. Если вас это не устраивает, вы можете начать с увеличения port_range . Установка диапазона 15000 61000 довольно распространена в наши дни. Вы можете еще больше увеличить доступность, уменьшив fin_timeout . Предположим, что вы делаете оба, вы должны видеть более 1500 исходящих подключений в секунду, с большей готовностью.

Чтобы изменить значения :

Вышесказанное не следует интерпретировать как факторы, влияющие на способность системы устанавливать исходящие соединения в секунду. Но скорее эти факторы влияют на способность системы обрабатывать параллельные соединения устойчивым образом в течение больших периодов «активности».

Значения Sysctl по умолчанию в стандартном окне Linux для tcp_tw_recycle & tcp_tw_reuse будут

Они не разрешают соединение из «используемого» сокета (в состоянии ожидания) и заставляют сокеты длиться полный time_wait цикл. Я рекомендую установить:

Это позволяет быстро переключать сокеты в time_wait состояние и повторно использовать их. Но перед тем, как вы сделаете это изменение, убедитесь, что оно не конфликтует с протоколами, которые вы используете для приложения, которому нужны эти сокеты. Обязательно прочитайте пост «Как справиться с TCP-TIME-WAIT» от Винсента Берната, чтобы понять последствия. Эта net.ipv4.tcp_tw_recycle опция довольно проблематична для общедоступных серверов, поскольку она не будет обрабатывать соединения от двух разных компьютеров за одним и тем же устройством NAT , что является проблемой, которую трудно обнаружить и которая ждет вас. Обратите внимание, что net.ipv4.tcp_tw_recycle было удалено из Linux 4.12.

На стороне сервера: net.core.somaxconn значение играет важную роль. Это ограничивает максимальное количество запросов в очереди к сокету прослушивания. Если вы уверены в возможностях вашего серверного приложения, увеличьте его значение по умолчанию со 128 до 128 — 1024. Теперь вы можете воспользоваться этим увеличением, изменив переменную listen backlog в вызове listen вашего приложения на равное или большее целое число.

txqueuelen Параметр ваших карт Ethernet также играют свою роль. Значения по умолчанию — 1000, поэтому увеличьте их до 5000 или даже больше, если ваша система справится с этим.

Аналогичным образом увеличьте значения для net.core.netdev_max_backlog и net.ipv4.tcp_max_syn_backlog . Их значения по умолчанию 1000 и 1024 соответственно.

Теперь не забудьте запустить как клиентские, так и серверные приложения, увеличивая значения FD в оболочке.

Помимо вышесказанного, еще одна популярная техника, используемая программистами, заключается в сокращении количества вызовов tcp-записи . Я предпочитаю использовать буфер, в который я помещаю данные, которые я хочу отправить клиенту, а затем в соответствующих точках записываю буферизованные данные в реальный сокет. Этот метод позволяет мне использовать большие пакеты данных, уменьшить фрагментацию, уменьшить загрузку процессора как на уровне пользователя, так и на уровне ядра.

Читайте также:  Как записать windows флешку с помощью ultraiso

Источник

Настройка сетевого стека Linux для высоконагруженных систем

Максимизируем количество входящих соединений

Приглашаем всех желающих посетить открытый демо-урок «Практикум по написанию Ansible роли». На этом вебинаре участники вместе с экспертом будут писать, тестировать и отлаживать ansible роли. Это важно для тех, кто хочет автоматизировать настройку инфраструктуры, поскольку это один из инструментов, который это позволяет сделать. Сетевой стек — одна из самых запутанных вещей в Linux. И не только из-за сложности некоторых концепций и терминов, но и из-за изменения смысла некоторых параметров в разных версиях ядра. В этой статье приведена информация для ядра 2.2 и выше, а также, там где это возможно, указано различие между версиями вплоть до 5.5.

Очередь приема и netdev_max_backlog

Каждое ядро процессора перед обработкой пакетов сетевым стеком может хранить их в кольцевом буфере. Если буфер заполняется быстрее, чем TCP-стек обрабатывает пакеты, то пакеты отбрасываются и увеличивается счетчик отброшенных пакетов (dropped packet counter). Для увеличения размера очереди следует использовать параметр net.core.netdev_max_backlog .

net.core.netdev_max_backlog — параметр задается на ядро процессора.

Очередь ожидающих запросов на соединение и tcp_max_syn_backlog

Соединения создаются для SYN-пакетов из очереди приема и перемещаются в очередь ожидания (SYN Backlog Queue). Также соединение помечается как «SYN_RECV» и клиенту отправляется «SYN+ACK». Эти соединения не перемещаются в очередь установленных соединений ожидающих обработки accept() (accept queue) до тех пор, пока не будет получен и обработан соответствующий ACK. Максимальное количество соединений в этой очереди устанавливается параметром net.ipv4.tcp_max_syn_backlog .

Для просмотра очереди приема используйте команду netstat . На правильно настроенном сервере при нормальной нагрузке значение не должно быть больше 1. При большой нагрузке значение должно быть меньше размера очереди ожидания (SYN Backlog):

Если в состоянии «SYN_RECV» находятся много соединений, то можно также подстроить продолжительность нахождения SYN-пакета в этой очереди.

Если SYN cookie отключены, то клиент просто повторяет отправку SYN-пакета. Если включены (net.ipv4.tcp_syncookies), то соединение не создается и не помещается в SYN backlog, но клиенту отправляется SYN+ACK так, как если бы это было сделано на самом деле. SYN cookie могут быть полезны при нормальной нагрузке, но при всплесках трафика некоторая информация о соединении может быть потеряна и клиент столкнется с проблемами, когда соединение будет установлено. Подробнее о SYN cookie можно прочитать в статье Грэма Коула (Graeme Cole) SYN cookies ate my dog (SYN cookie съели мою собаку), в которой подробно объясняется, почему включение SYN cookie на высоконагруженных серверах может привести к проблемам.

Повторы SYN+ACK

Что происходит, если SYN+ACK отправлен, но ответа ACK нет? В этом случае сетевой стек сервера повторит отправку SYN+ACK. Задержка между попытками вычисляется таким образом, чтобы обеспечить восстановление сервера. Если сервер получает SYN и отправляет SYN+ACK, но не получает ACK, то тайм-аут повторной передачи вычисляется по экспоненте (Exponental Backoff) и, следовательно, зависит от количества повторных попыток. Количество повторных попыток отправки SYN+ACK задается параметром ядра net.ipv4.tcp_synack_retries (по умолчанию равно 5). Повторные попытки будут через следующие интервалы: 1с, 3с, 7с, 15с, 31с. При шести попытках последняя будет примерно через 63 секунды после первой. Это позволяет удержать SYN-пакет в очереди ожидания более 60 секунд до истечения времени ожидания пакета. Если очередь SYN backlog мала, то не требуется большого количества соединений, чтобы возникла ситуация, когда полуоткрытые соединения никогда не завершатся и тогда никакие соединения не смогут быть установлены. Установите количество повторных попыток SYN+ACK равным 0 или 1, чтобы избежать такого поведения на высоконагруженных серверах.

Читайте также:  Как самому сделать сборку windows 10 самому

Повторы SYN

Несмотря на то что повторные SYN-пакеты отправляются клиентом во время ожидания SYN+ACK, они могут влиять и на высоконагруженные серверы, работающие с прокси-соединениями. Например, сервер nginx, устанавливающий несколько десятков прокси-соединений к бэкенд-серверу, из-за всплесков трафика может на некоторое время перегрузить сетевой стек, а повторные попытки создадут дополнительную нагрузку на бэкэнд как в очереди приема, так и в очереди ожидания (SYN backlog). Это, в свою очередь, может повлиять на клиентские соединения. Повторные попытки SYN контролируются параметром net.ipv4.tcp_syn_retries (по умолчанию 5 или 6 в зависимости от дистрибутива). Ограничьте количество повторных попыток SYN до 0 или 1, чтобы не было долгих повторных попыток отправки в течение 63–130 с.

Более подробно о проблемах с клиентскими соединениями при обратном прокси-сервере читайте в статье Linux Kernel Tuning for High Performance Networking: Ephemeral Ports.

Очередь установленных соединений ожидающих принятия (accept queue) и somaxconn

Очередь запросов на соединение создает приложение, используя listen() и указывая размер очереди в параметре «backlog». Начиная с ядра 2.2 поведение этого параметра изменилось с максимального количества неоконченных запросов на соединение, которое может удерживать сокет, на максимальное количество полностью установленных соединений, ожидающих, пока они будут приняты. Как описано выше, максимальное количество неоконченных запросов на соединение теперь задается с помощью параметра ядра net.ipv4.tcp_max_syn_backlog .

somaxconn и параметр backlog в listen()

Хотя за размер очереди для каждого слушателя отвечает приложение, есть ограничение на количество соединений, которые могут находиться в очереди. Размером очереди управляют два параметра: 1) параметр backlog в функции listen() и 2) параметр ядра net.core.somaxconn , задающий максимальный размер очереди.

Значения по умолчанию для очереди

Значение по умолчанию для net.core.somaxconn берется из константы SOMAXCONN, которая в ядрах Linux вплоть до версии 5.3 имеет значение 128, но в 5.4 она была увеличена до 4096. Однако, на момент написания этой статьи, ядро 5.4 еще не очень распространено, поэтому в большинстве систем значение будет 128, если вы не модифицировали net.core.somaxconn.

Часто приложения для размера очереди по умолчанию используют константу SOMAXCONN, если этот размер не задается в конфигурации приложения. Хотя некоторые приложения устанавливают и свои значения по умолчанию. Например, в nginx размер очереди равен 511, который автоматически усекается до 128 в ядрах Linux до версии 5.3.

Изменение размера очереди

Многие приложения позволяют указывать размер очереди в конфигурации, указывая значение параметра backlog для listen() . Если приложение вызывает listen() со значением backlog , превышающим net.core.somaxconn, то размер очереди будет автоматически усечен до значения SOMAXCONN.

Потоки

Если очередь большая, то подумайте также об увеличении количества потоков, которые обрабатывают запросы в приложении. Например, установка для nginx очереди ожидания в 20480 для HTTP-listener без достаточного количества worker_connections для управления очередью приведет к тому, что сервер будет отказываться отвечать на запросы на установку соединения.

Соединения и файловые дескрипторы

Системные ограничения

Любое сокетное соединение использует файловый дескриптор. Максимальное количество дескрипторов, которые могут быть созданы в системе, задается параметром ядра fs.file-max. Посмотреть количество используемых дескрипторов можно следующим образом:

Вывод показывает, что используется 1976 файловых дескрипторов. Выделено, но не используется 12 (для ядер 2.6+), а максимальное количество — 2048. В высоконагруженной системе значение должно быть достаточно большим, чтобы справиться как с большим количеством соединений, так и с потребностями в файловых дескрипторах других процессов.

Пользовательские ограничения

Помимо системного ограничения количества файловых дескрипторов, у каждого пользователя есть свои лимиты. Они настраиваются в системном файле limits.conf (nofile) или, при запуске процесса под управлением systemd, в unit-файле systemd (LimitNOFILE). Чтобы увидеть значение по умолчанию запустите:

Для systemd (на примере nginx):

Настройка

Для настройки системных ограничений установите параметр ядра fs.max-file в максимальное количество файловых дескрипторов, которое может быть в системе (с учетом некоторого буфера). Например:

Читайте также:  Linux bash проверка существования файла

Для настройки пользовательского лимита установите достаточно большое значение, чтобы хватило сокетам и файловым дескрипторам рабочих процессов (также с некоторым буфером). Пользовательские ограничения устанавливаются в /etc/security/limits.conf, в conf-файле в /etc/security/limits.d/ или в unit-файле systemd. Например:

Количество worker’ов

Аналогично файловым дескрипторам, количество worker’ов или потоков, которые может создать процесс, ограничено как на уровне ядра, так и на уровне пользователя.

Системные ограничения

Процессы могут создавать рабочие потоки. Максимальное количество потоков, которые могут быть созданы, задается параметром ядра kernel.threads-max . Для просмотра максимального и текущего количества потоков, выполняющихся в системе, запустите следующее:

Пользовательские ограничения

Есть свои ограничения и у каждого пользовательского процесса. Это также настраивается с помощью файла limits.conf (nproc) или unit-файла systemd (LimitNPROC). Для просмотра максимального количества потоков, которое может создать пользователь запустите:

Для systemd (на примере nginx):

Настройка

В большинстве случаев системные ограничения достаточно большие, чтобы справиться с высокой нагрузкой. Однако их можно настроить через параметр ядра kernel.threads-max . Установите его значение в максимальное количество потоков, необходимых системе, плюс некоторый буфер. Например:

Как и в случае с nofile , ограничения для пользователей ( nproc ) устанавливаются в /etc/security/limits.conf, в conf-файле в /etc/security/limits.d/ или в unit-файле systemd. Пример с nproc и nofile :

Обратный прокси и TIME_WAIT

При большом всплеске трафика прокси-соединения, застрявшие в «TIME_WAIT», суммарно могут потреблять много ресурсов при закрытии соединения. Это состояние говорит, что клиент получил последний FIN-пакет от сервера (или вышестоящего worker’а) и находится в ожидании для корректной обработки пакетов. Время нахождения соединения в состоянии «TIME_WAIT» по умолчанию составляет 2 x MSL (Maximum Segment Length — максимальная длина сегмента), что составляет 2 x 60 с. В большинстве случаев это нормальное и ожидаемое поведение, и значение по умолчанию в 120 с вполне приемлемо. Однако много соединений в состоянии «TIME_WAIT» может привести к тому, что приложение исчерпает эфемерные порты для соединений к клиентскому сокету. В этом случае следует уменьшить FIN тайм-аут.

Управляет этим тайм-аутом параметр net.ipv4.tcp_fin_timeout . Рекомендуемое значение для высоконагруженных систем составляет от 5 до 7 секунд.

Собираем все вместе

Очередь приема (receive queue) должна быть рассчитана на обработку всех пакетов, полученных через сетевой интерфейс, не вызывая отбрасывания пакетов. Также необходимо учесть небольшой буфер на случай, если всплески будут немного выше, чем ожидалось. Для определения правильного значения следует отслеживать файл softnet_stat на предмет отброшенных пакетов. Эмпирическое правило — использовать значение tcp_max_syn_backlog, чтобы разрешить как минимум столько же SYN-пакетов, сколько может быть обработано для создания полуоткрытых соединений. Помните, что этот параметр задает количество пакетов, которое каждый процессор может иметь в своем буфере, поэтому разделите значение на количество процессоров.

Размер SYN очереди ожидания (SYN backlog queue) на высоконагруженном сервере должен быть рассчитан на большое количество полуоткрытых соединений для обработки редких всплесков трафика. Здесь эмпирическое правило заключается в том, чтобы установить это значение, по крайней мере, на максимальное количество установленных соединений, которое слушатель может иметь в очереди приема, но не выше, чем удвоенное количество установленных соединений. Также рекомендуется отключить SYN cookie, чтобы избежать потери данных при больших всплесках соединений от легитимных клиентов.

Очередь установленных соединений, ожидающих принятия (accept queue) должна быть рассчитана таким образом, чтобы в периоды сильного всплеска трафика ее можно было использовать в качестве временного буфера для установленных соединений. Эмпирическое правило — устанавливать это значение в пределах 20–25% от числа рабочих потоков.

Параметры

В этой статье были рассмотрены следующие параметры ядра:

И следующие пользовательские ограничения:

Заключение

Все параметры в этой статье приведены в качестве примеров и не должны вслепую применяться на ваших продакшн-серверах без тестирования. Есть и другие параметры ядра, которые влияют на производительность сетевого стека. Но в целом, это наиболее важные параметры, которые я использовал при настройке ядра для высоконагруженных систем.

Источник

Оцените статью