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

90

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

Во время нагрузочного тестирования сервера Apache с ab я заметил, что довольно просто максимально увеличить количество открытых соединений на сервере. Если вы отключите опцию ab's -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
Бен Уильямс
источник

Ответы:

64

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

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поскольку документы подразумевают, что это опасно.

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

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, но для меня это не так.

Бен Уильямс
источник
3
Где мы настраиваем эти параметры?
Codevalley
2
@Codevalley Это может зависеть от системы, но на сервере Ubuntu они находятся в /etc/sysctl.conf
Бен Уильямс,
24

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

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

  • / proc / sys / net / ipv4 / tcp_max_orphans , который контролирует максимальное количество сокетов, удерживаемых системой, не прикрепленной к чему-либо. Увеличение этого значения может потреблять до 64 Кбайт памяти, не подлежащей замене, на каждый потерянный сокет .
  • / proc / sys / net / ipv4 / tcp_orphan_retries , который контролирует количество попыток, прежде чем сокет будет потерян и закрыт. На этой странице есть отдельная заметка о веб-серверах, которая вас непосредственно интересует ...
Эйвери Пэйн
источник
tcp_max_orphans интересен, но кажется, что он не работает. Когда я пытаюсь измерить осиротевшие сокеты во время теста, я вижу 11 651 из них, тогда как tcp_max_orphans равен 8 092. # netstat --inet -p | grep "localhost: www" | sed -e 's / \ + / / g' | cut -d '' -f 1-4,6-7 | сортировать | uniq -c 11651 tcp 0 0 localhost: www TIME_WAIT -
Бен Уильямс
Посмотрите на настройку tcp_orphan_retries - идея в том, что сокеты «отбраковываются» быстрее ...
Avery Payne
Предложение @Jauder Ho + tcp_orphan_retries звучит как потенциальная победа в вашей ситуации.
Эйвери Пейн
3

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

Кайл Брандт
источник
2

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

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
Джодер Хо
источник
Осторожнее здесь! Опытный трудный путь. «Это может привести к пропущенным кадрам с балансировкой нагрузки и NAT, используйте это только для сервера, который обменивается данными только по локальной сети». - wiki.archlinux.org/index.php/Sysctl
Хенк
@Henk Я думаю tcp_tw_recycle, это потенциально опасно. tcp_tw_reuseбезопаснее, и я не вижу смысла использовать их одновременно.
Владислав Раструсный
2

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

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

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

rasjani
источник
1

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

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

Девдас
источник
1
tcp_fin_timeout предназначен не для установки срока действия TIME-WAIT, который нельзя изменить вне перестроения ядра, а для FIN, как видно из названия.
Александр Курилин
0

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

Джейсон Тан
источник
6
Нет, это не так. Вы можете открыть больше, так как локальный порт не должен быть уникальным, если удаленные адреса разные. Более того, OP указывает на сервер, и вы можете иметь> 1 адрес на сервер.
MarkR