Назад | Перейти на главную страницу

Что ограничивает максимальное количество подключений на сервере Linux?

Какие параметры ядра или другие параметры определяют максимальное количество сокетов TCP, которые могут быть открыты на сервере Linux? Каковы компромиссы при разрешении большего количества подключений?

Во время нагрузочного тестирования я заметил сервер Apache с ab что довольно легко максимально увеличить количество открытых соединений на сервере. Если вы оставите опцию ab -k, которая разрешает повторное использование соединения, и попросите его отправить более 10 000 запросов, то Apache обслужит первые 11 000 или около того запросов, а затем остановится на 60 секунд. Взгляд на вывод netstat показывает 11 000 соединений в состоянии TIME_WAIT. Судя по всему, это нормально. Соединения остаются открытыми по умолчанию 60 секунд даже после того, как клиент завершил с ними работу в течение Причины надежности TCP.

Похоже, это был бы простой способ DoS-атаки сервера, и мне интересно, каковы обычные настройки и меры предосторожности для него.

Вот мой тестовый результат:

# ab -c 5 -n 50000 http://localhost/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 5000 requests
Completed 10000 requests
apr_poll: The timeout specified has expired (70007)
Total of 11655 requests completed

Вот команда netstat, которую я выполняю во время теста:

 # netstat --inet -p | grep "localhost:www" | sed -e 's/ \+/ /g' | cut -d' ' -f 1-4,6-7 | sort | uniq -c 
  11651 tcp 0 0 localhost:www TIME_WAIT -
      1 tcp 0 1 localhost:44423 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44424 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44425 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44426 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44428 SYN_SENT 7831/ab

Наконец я нашел настройку, которая действительно ограничивала количество подключений: net.ipv4.netfilter.ip_conntrack_max. Было установлено 11,776, и все, что я установил, это количество запросов, которые я могу обслужить в своем тесте, прежде чем мне придется ждать. tcp_fin_timeout секунд, чтобы стало доступно больше соединений. В conntrack table - это то, что ядро ​​использует для отслеживания состояния соединений, поэтому после заполнения ядро ​​начинает отбрасывать пакеты и печатать это в журнале:

Jun  2 20:39:14 XXXX-XXX kernel: ip_conntrack: table full, dropping packet.

Следующим шагом было заставить ядро ​​перезапустить все эти соединения в TIME_WAIT состояние, а не отбрасывание пакетов. Я мог бы добиться этого, включив tcp_tw_recycle или увеличение ip_conntrack_max быть больше, чем количество локальных портов, доступных для подключений ip_local_port_range. Я предполагаю, что как только ядро ​​выходит из локальных портов, оно начинает перерабатывать соединения. Это использует больше соединений для отслеживания памяти, но это кажется лучшим решением, чем включение tcp_tw_recycle так как документы подразумевают, что это опасно.

С этой конфигурацией я могу работать весь день и никогда не останавливаться на достигнутом:

net.ipv4.netfilter.ip_conntrack_max = 32768
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_orphan_retries = 1
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_max_orphans = 8192
net.ipv4.ip_local_port_range = 32768    61000

В tcp_max_orphans настройка не повлияла на мои тесты, и я не знаю почему. Я бы подумал, что это закроет связи в TIME_WAIT заявляю, что когда-то их было 8192, но для меня это не так.

Вы действительно хотите посмотреть, что файловая система / proc может предложить вам в этом отношении.

На этой последней странице вас могут заинтересовать следующие материалы:

  • / proc / sys / net / ipv4 / tcp_max_orphans, который контролирует максимальное количество сокетов, удерживаемых системой не к чему-то привязан. Повышение этого может потреблять до 64 Кбайт неподключаемой памяти. на сиротскую розетку.
  • / proc / sys / net / ipv4 / tcp_orphan_retries, который контролирует количество повторных попыток перед тем, как сокет будет потерян и закрыт. На этой странице есть специальная заметка о веб-серверах, которая вас интересует ...

Я не думаю, что есть возможность настроить это напрямую. Это подпадает под категорию настройки TCP / IP. Чтобы узнать, что можно настроить, попробуйте «man 7 tcp». Для их установки используется sysctl ('man 8 sysctl'). 'sysctl -a | grep tcp 'покажет вам большую часть того, что вы можете настроить, но я не уверен, что он покажет все из них. Кроме того, если это не изменилось, открывающиеся сокеты TCP / IP выглядят как файловые дескрипторы. Так этот и следующий раздел в этой ссылке может быть тем, что вы ищете.

Попробуйте также установить следующее: tcp_fin_timeout. Это должно закрыть TIME_WAIT быстрее.

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

Стандартный apache (1) изначально предопределен для поддержки только 250 одновременных подключений - если вам нужно больше, нужно было изменить один файл заголовка, чтобы разрешить больше одновременных сеансов. Я не знаю, верно ли это для Apache 2.

Кроме того, вам необходимо добавить возможность разрешить загрузку большего количества дескрипторов открытых файлов для учетной записи, в которой работает Apache, - то, что не упоминается в предыдущих комментариях.

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

Вы можете сократить время нахождения в состоянии TIME_WAIT (Установите net.ipv4.tcp_fin_timeout). Вы можете заменить Apache на YAWS, nginx или что-то подобное.

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

Абсолютное количество сокетов, которые могут быть открыты на одном IP-адресе, равно 2 ^ 16 и определяется TCP / UDP, а не ядром.

Инструмент тестирования HTTP-сервера Apache, ab, в версии 2.4 есть -s тайм-аут вариант. Смотрите также Ошибка ab (Apache Bench): apr_poll: время ожидания истекло (70007) в Windows.

Этот вариант решает вашу проблему.