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

Какой параметр ядра или другие параметры определяют максимальное количество сокетов 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

8 ответов

Решение

Я наконец нашел параметр, который действительно ограничивал количество соединений: 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, но это не для меня.

Вы действительно хотите посмотреть, что файловая система / 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 или что-то подобное.

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

У инструмента тестирования производительности HTTP-сервера Apache ab в версии 2.4 есть опция -s timeout. См. Также ошибка ab (Apache Bench): apr_poll: истекло указанное время ожидания (70007) в Windows.

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

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

Другие вопросы по тегам