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