← Весь справочник

ab (Apache Bench)

Нагрузочный тест HTTP-сервера — число запросов, параллельность, keep-alive и как читать отчёт

ab (ApacheBench, пакет apache2-utils) шлёт на один URL заданное число HTTP-запросов, несколько одновременно, и печатает отчёт: сколько запросов в секунду выдержал сервер, сколько из них упало и как распределилось время ответа. Подходит для быстрой оценки «до и после» на одном URL; сценарии из многих страниц он не умеет.

Синтаксис

ab [опции] http://хост[:порт]/путь

Путь обязателен: http://127.0.0.1:8080 без завершающего / — ошибка invalid URL.

Опции

Объём и параллельность

ОпцияЧто делает
-n Nвсего запросов (по умолчанию 1)
-c Nсколько запросов держать одновременно (по умолчанию 1); не может быть больше -n
-t секработать не дольше стольких секунд; сам ставит -n 50000
-kkeep-alive: переиспользовать соединения вместо нового TCP на каждый запрос
-s сексколько ждать каждый ответ (по умолчанию 30)
-rне прерывать тест при ошибках чтения сокета

Запрос

ОпцияЧто делает
-m МЕТОДпроизвольный метод
-iHEAD вместо GET
-p файлPOST с телом из файла; вместе с ним задай -T
-u файлPUT с телом из файла
-T типContent-Type для -p / -u (по умолчанию text/plain)
-H 'Имя: значение'добавить заголовок; можно повторять
-C 'имя=значение'добавить cookie
-A логин:парольBasic-авторизация
-X прокси:портходить через прокси

Отчёт

ОпцияЧто делает
-qне печатать прогресс Completed 100 requests
-lне считать ошибкой разную длину ответов (для динамических страниц)
-dне печатать таблицу процентилей
-Sне печатать среднеквадратичные отклонения
-e файл.csvпроцентили в CSV
-g файл.tsvвсе замеры в формате gnuplot
-v Nподробность отладки: 2 и выше печатает заголовки

Как читать отчёт

Concurrency Level:      10
Time taken for tests:   0.018 seconds
Complete requests:      200
Failed requests:        0
Non-2xx responses:      20
Keep-Alive requests:    100
Requests per second:    10897.40 [#/sec] (mean)
Time per request:       0.918 [ms] (mean)
Time per request:       0.092 [ms] (mean, across all concurrent requests)
Transfer rate:          2596.65 [Kbytes/sec] received
СтрокаСмысл
Document Lengthразмер тела первого ответа; от него считаются «ошибки длины»
Complete requestsсколько запросов получили ответ
Failed requestsсбои: в скобках Connect, Receive, Length (тело другой длины), Exceptions
Non-2xx responsesответы с кодом не 2xx — в Failed они не входят (строка появляется, только если такие были)
Keep-Alive requestsсколько запросов ушло по уже открытым соединениям (только с -k)
Requests per secondпропускная способность — главная цифра
Time per request (первая)среднее время одного запроса с точки зрения клиента
Time per request (across all)первая, делённая на -c — по сути 1/RPS
Connection TimesConnect — установка TCP, Waiting — до первого байта ответа, Processing — от соединения до конца ответа, Total — итог
Percentage … served withinпроцентили: 95% 4 — 95 % запросов уложились в 4 мс; 100% — самый долгий

Коды выхода

0 — тест прошёл (даже если были Failed и Non-2xx!); ненулевой — тест не удалось провести: неверный URL, опции, сервер недоступен.

Примеры

# 1000 запросов, по 50 одновременно
ab -n 1000 -c 50 http://127.0.0.1:8080/

# то же с keep-alive — обычно в разы быстрее
ab -k -n 1000 -c 50 http://127.0.0.1:8080/

# гонять 10 секунд без прогресса и выбрать главное
ab -q -t 10 -c 20 http://127.0.0.1:8080/ | grep -E 'Requests per second|Failed|Non-2xx|95%'

# POST с телом из файла
echo 'name=demo' > body.txt
ab -n 100 -c 10 -p body.txt -T application/x-www-form-urlencoded http://127.0.0.1:8080/api/form

# страница за Basic-авторизацией, свой заголовок
ab -n 200 -c 10 -A admin:secret -H 'Accept: application/json' http://127.0.0.1:8080/private/

# динамическая страница с разной длиной ответа
ab -l -n 500 -c 20 http://127.0.0.1:8080/dynamic

# процентили в CSV для графика
ab -n 1000 -c 20 -e percentiles.csv http://127.0.0.1:8080/ >/dev/null

Подводные камни

  • 404 и 500 — не Failed. Ответы с ошибкой считаются «успешными» запросами и попадают в строку Non-2xx responses. Высокий RPS при сплошных 404 ничего не значит — всегда смотри эту строку. Код выхода ab при этом тоже 0.
  • Failed requests с Length на динамической странице — не ошибка сервера: просто тело каждый раз разной длины. Добавь -l.
  • Без / в конце URL ab сразу падает с invalid URL: http://127.0.0.1:8080/, а не http://127.0.0.1:8080.
  • -c больше -n запрещён — Cannot use concurrency level greater than total number of requests.
  • Без -k каждый запрос — новое TCP-соединение. Цифры получаются заметно хуже, чем у браузера, который держит соединения открытыми.
  • ab сам отнимает CPU. Если он запущен на той же машине, что и сервер, они делят процессор, и результат занижен.
  • -p к статическому файлу в nginx вернёт 405 — всё уйдёт в Non-2xx.
  • Один URL — не реальная нагрузка. Кэш отдаёт одну и ту же страницу; реальные пользователи ходят по разным адресам.

См. также

curl · wget · nginx · htpasswd · top