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 |
-k | keep-alive: переиспользовать соединения вместо нового TCP на каждый запрос |
-s сек | сколько ждать каждый ответ (по умолчанию 30) |
-r | не прерывать тест при ошибках чтения сокета |
Запрос
| Опция | Что делает |
|---|---|
-m МЕТОД | произвольный метод |
-i | HEAD вместо 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 Times | Connect — установка 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.- Без
/в конце URLabсразу падает с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 — не реальная нагрузка. Кэш отдаёт одну и ту же страницу; реальные пользователи ходят по разным адресам.