А вот я справился с этим траблом!
Вот пример результата при тестировании локалхоста с запросом HTML:
Код: Выделить всё
# ab -n 1000000 -c 500 http://127.0.0.1:81/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Server Software: Apache
Server Hostname: 127.0.0.1
Server Port: 81
Document Path: /
Document Length: 1152 bytes
Concurrency Level: 500
Time taken for tests: 330.425 seconds
Complete requests: 1000000
Failed requests: 0
Write errors: 0
Total transferred: 1392000000 bytes
HTML transferred: 1152000000 bytes
Requests per second: 3026.40 [#/sec] (mean)
Time per request: 165.213 [ms] (mean)
Time per request: 0.330 [ms] (mean, across all concurrent requests)
Transfer rate: 4114.02 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 8 140.1 0 6209
Processing: 6 158 104.7 139 3925
Waiting: 6 157 104.7 139 3925
Total: 12 165 176.0 139 9951
Percentage of the requests served within a certain time (ms)
50% 139
66% 173
75% 216
80% 245
90% 310
95% 360
98% 412
99% 440
100% 9951 (longest request)
Трабл оказался связан с тем как ab и apache обращаются с WAIT-сокетами локалхоста. У них это как-то криво сделано, они обязательно нуждаются в их наличии. В результате, если в sysctl имеется net.inet.tcp.nolocaltimewait=1 (не создавать состояния TIME_WAIT для соединений localhost), ab падает с ошибкой "apr_socket_connect(): Can't assign requested address".
Кроме того, для большого потока запросов на локалхост, ab нуждается в максимально возможном количестве "compressed TCP TIME_WAIT entries", указываемых через net.inet.tcp.maxtcptw. Там нужно прописывать половину имеющихся сокетов.
Когда ab тестирует apache на localhost, видно как идут волны нарастания и спада количества занятых сокетов. Посмотреть можно так:
Код: Выделить всё
# sysctl kern.ipc.numopensockets && netstat -an | grep -c TIME_WAIT
kern.ipc.numopensockets: 36690
33692
А вот при тестировании nginx ситуация другая, там никаких волн нет, держится на одном уровне:
Код: Выделить всё
#sysctl kern.ipc.numopensockets && netstat -an | grep -c TIME_WAIT
kern.ipc.numopensockets: 25057
84866
Кстати, сравнительный результат примерно такой:
Код: Выделить всё
Server Software: nginx
Server Hostname: 127.0.0.1
Server Port: 80
Document Path: /
Document Length: 1152 bytes
Concurrency Level: 500
Time taken for tests: 245.439 seconds
Complete requests: 1000000
Failed requests: 1
(Connect: 0, Receive: 0, Length: 1, Exceptions: 0)
Write errors: 0
Total transferred: 1390998609 bytes
HTML transferred: 1151998848 bytes
Requests per second: 4074.33 [#/sec] (mean)
Time per request: 122.719 [ms] (mean)
Time per request: 0.245 [ms] (mean, across all concurrent requests)
Transfer rate: 5534.56 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 54 381.1 6 9409
Processing: 0 68 364.5 19 26733
Waiting: 0 67 363.7 19 26733
Total: 10 122 533.0 25 26739
Percentage of the requests served within a certain time (ms)
50% 25
66% 26
75% 27
80% 27
90% 30
95% 255
98% 3025
99% 3027
100% 26739 (longest request)
То есть, nginx примерно в полтора раза быстрее. Малая величина RPS в обоих случаях - следствие вредного воздействия PF, который имеет странную особенность после некоторого количества запросов тормозить поток запросов без превышения лимитов и сильно задерживать ответы (см. longest request). Сейчас пытаюсь понять как преодолеть этот эффект.
В целом, ab пользоваться можно, у него есть некоторые полезные параметры в результатах. Я по очереди использую ab и Siege.