«ab» программа зависает после множества запросов, почему?
Всякий раз, когда я использую «ab» для тестирования веб-сервера, он некоторое время замерзает после того, как отправил много запросов, только для продолжения через 20 секунд или около того.
Рассмотрим следующий симулятор HTTP-сервера, написанный на Ruby:
require 'socket' RESPONSE = "HTTP/1.1 200 OK\r\n" + "Connection: close\r\n" + "\r\n" + "\r\n" buffer = "" server = TCPServer.new("127.0.0.1", 3000) # Create TCP server at port 3000. server.listen(1024) # Set backlog to 1024. while true client = server.accept # Accept new client. client.write(RESPONSE) # Write a stock "HTTP" response. client.close_write # Shutdown write part of the socket. client.read(nil, buffer) # Read all data from the socket. client.close # Close it. end
Затем я запускаю ab следующим образом:
- Как проверить наличие интернет-соединения в java?
- Как рассчитать количество параметров для сверточной нейронной сети?
- Как настроить статический IP-адрес, сетевую маску, шлюз программно на Android 3.x или 4.x
- Сетевые инструменты, которые имитируют медленное сетевое подключение
- В чем разница между 127.0.0.1 и localhost
ab -n 45000 -c 10 http://127.0.0.1:3000/
В течение первых нескольких секунд ab выполняет свою работу так, как предполагается, и использует 100% процессор:
Benchmarking 127.0.0.1 (be patient) Completed 4500 requests Completed 9000 requests Completed 13500 requests
После примерно 13500 запросов загрузка системного процессора падает до 0%. Кажется, что что-то замерзло. Проблема не в сервере, потому что на данный момент сервер вызывает accept (). Примерно через 20 секунд ab продолжает, как будто ничего не происходит, и снова будет использовать 100% CPU, только чтобы снова заморозить через несколько секунд.
Я подозреваю, что что-то в ядре дросселирует соединения, но что и почему? Я использую OS X Leopard. Я также видел подобное поведение в Linux, хотя замораживание происходит при гораздо большем числе запросов и происходит не так часто.
Эта проблема не позволяет мне запускать большие тесты HTTP.
- Как я могу получить «сетевое» время (из параметра «Автоматический» под названием «Использовать сетевые значения»), а не время на телефоне?
- Параметр TCP SO_LINGER (ноль) - когда требуется
- Обнаружение скорости сетевого соединения и использования полосы пропускания в C #
- Как я могу прервать метод acceptSetServerSocket?
- close vs shutdown socket?
- Проверка доступности хоста с помощью ping в сценариях bash
- Поддерживает ли ServerSocket обратный сокет на произвольном порту?
- Как изменить параметры сети (IP-адрес, DNS, WINS, имя хоста) с кодом в C #
Похоже, что у вас заканчиваются эфемерные порты . Чтобы проверить, используйте команду netstat
и найдите несколько тысяч портов в TIME_WAIT
.
В Mac OS X диапазон эфемерных портов по умолчанию составляет от 49152 до 65535, в общей сложности – 16384 порта. Вы можете проверить это с помощью команды sysctl
:
$ sysctl net.inet.ip.portrange.first net.inet.ip.portrange.last net.inet.ip.portrange.first: 49152 net.inet.ip.portrange.last: 65535
Как только вы закончите эфемерные порты, вам, как правило, нужно подождать, пока истечет срок действия TIME_WAIT
(максимальный срок службы сегмента 2 *), пока вы не сможете повторно использовать определенный номер порта. Вы можете удвоить количество портов, изменив диапазон, чтобы начать с 32768, что по умолчанию используется для Linux и Solaris. (Максимальный номер порта – 65535, поэтому вы не можете увеличить высокий уровень.)
$ sudo sysctl -w net.inet.ip.portrange.first = 32768 net.inet.ip.portrange.first: 49152 -> 32768
Обратите внимание, что официальный диапазон, обозначенный IANA, составляет от 49152 до 65535, а некоторые брандмауэры могут предполагать, что динамически назначенные порты попадают в этот диапазон. Возможно, вам понадобится перенастроить ваш брандмауэр, чтобы использовать более широкий диапазон вне вашей локальной сети.
Также возможно сократить максимальное время жизни сегмента ( sysctl net.inet.tcp.msl
в Mac OS X), который контролирует продолжительность состояния TIME_WAIT
, но это опасно, так как это может привести к тому, что старые соединения будут запутаны с новыми которые используют один и тот же номер порта. Также есть некоторые трюки, связанные с привязкой к конкретным портам с опцией SO_REUSEADDR
или закрытие с помощью опции SO_LINGER
, но также могут быть смешаны старые и новые соединения, поэтому обычно считаются плохими идеями.
Вместо увеличения количества портов измените длину TIME_WAIT
на Mac OS X.
Это работает только в разработке, но теперь я могу запросить ab
столько запросов, сколько захочу, без учета времени.
Установите тайм-аут по умолчанию на 1000 мс следующим образом:
$ sudo sysctl -w net.inet.tcp.msl=1000 net.inet.tcp.msl: 15000 -> 1000
Страница brianp.net, указанная в другом ответе, больше не доступна. Вы можете получить его из интернет-архива .