Какой параметр ядра или другие параметры контролируют максимальное количество 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
Я наконец нашел параметр, который действительно ограничивал количество соединений: 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 может предложить вам в этом отношении.
На этой последней странице вам может быть интересно следующее:
Я не думаю, что есть возможность настроить это напрямую. Это подпадает под категорию настройки 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, а не ядром.