В данной статье разъясняются нюансы работы с wrk.
Главное: wrk не делает указанное кол-во запросов, он создает указанную нагрузку в течении указанного количества времени!
Для начала руководство:
-d, --duration: продолжительность испытания (время в течении которого wrk будет работать): 2s, 2m, 2h
-t, --threads: общее количество используемых потоков (один поток может делать несколько подключений)
-c, --connections: количеством одновременно выполняемых запросов (количество HTTP-соединений, которые нужно поддерживать открытыми в каждом потоке)
-s, --script: сценарий LuaJIT, см. раздел СЦЕНАРИИ
-H, --header: HTTP-заголовок для добавления в запрос, например "Агент пользователя: wrk"
--latency: печать подробной статистики задержки
--timeout: обрывать connection, если сервер не ответил за указанное тут количество секунд (на сервере будет 499)-t, если уже есть -c-c (connections) — сколько одновременных HTTP-соединений будет установлено.-t (threads) — сколько параллельных рабочих потоков будет обслуживать эти соединения.Хорошее правило: число потоков -t должно быть равно количеству CPU-ядер на машине, где запускается wrk.
Например на обычном 4-ядерном процессоре разумно использовать
-t4
-t1 и -c100Один поток будет обрабатывать все 100 соединений сам.
Это даст нагрузку, но недореализует потенциал CPU — поток просто не успевает обслуживать все соединения вовремя.
Как следствие — выше latency, меньше req/sec.
Get запрос - пример в котором мы делаем 2 одновременных запроса в течении 10 секунд:
docker run --rm williamyeh/wrk -t1 -c2 -d10s --timeout 5s https://yapro.ru/page?test=wrk1Post запрос - пример в котором мы сделаем 3 конкурентных POST-запроса, для этого создаем файл post.lua
wrk.method = "POST"
wrk.body = "{'hello':'world'}"
wrk.headers["Content-Type"] = "application/json"
local counter = 1
function response()
if counter == 3 then
wrk.thread:stop()
end
counter = counter + 1
endЗапускаем тест:
docker run --rm --net=host -v `pwd`:/data williamyeh/wrk -s post.lua -t1 -c1 -d2s http://my/api/pagedocker run --rm --net=host -v `pwd`:/data williamyeh/wrk -s post.lua -t1 -c3 -d1s http://my/api/page
Running 1s test @ http://my/api/page
1 threads and 3 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 0.00us 0.00us 0.00us -nan%
Req/Sec 0.00 0.00 0.00 -nan%
0 requests in 1.00s, 0.00B read
Requests/sec: 0.00
Transfer/sec: 0.00BНа самом деле запросы были, но:
3 connections означает, что было выполнено 3 подключения за 1 секунду (см. -d1s)0 requests означает было выполнено 0 успешных запросов за 1 секунду (см. -d1s), успешные это с http status 200wrk не стал дожидаться ответа и отключился через 1 сек:nginx_1 | 172.18.0.1 - - [24/Aug/2021:10:22:20 +0000] "POST /api/page HTTP/1.1" 499 0 "-" "-"
nginx_1 | 172.18.0.1 - - [24/Aug/2021:10:22:20 +0000] "POST /api/page HTTP/1.1" 499 0 "-" "-"
nginx_1 | 172.18.0.1 - - [24/Aug/2021:10:22:20 +0000] "POST /api/page HTTP/1.1" 499 0 "-" "-"
php-fpm_1 | 172.18.0.4 - 24/Aug/2021:10:22:19 +0000 "POST /index.php" 200
php-fpm_1 | 172.18.0.4 - 24/Aug/2021:10:22:19 +0000 "POST /index.php" 200
php-fpm_1 | 172.18.0.4 - 24/Aug/2021:10:22:32 +0000 "POST /index.php" 200Важно: таким образом, если веб-сервер не успевает обработать запросы за указанное время --timeout то мы неизбежно получим 499, а еще такие 499 мы всегда получаем в конце работы wrk ведь он просто обрывает соединения согласно (см. -d1s) .
LatencyAvg - среднее время ответа сервера на один запрос (сумму времени всех запросов делят на количество запросов)
Stdev (Standard deviation) - среднеквадратичное отклонение (см. хороший пример):
Max - максимальное время ответа
+/- Stdev - доля запросов, которые отклоняются от среднего в пределах одного стандартного отклонения.
Req/SecAvg - за сколько в среднем обрабатывается запрос (это точно не среднее количество запросов в секунду! уверен!)
Stdev - среднеквадратичное отклонение от самого быстрого запроса (могу ошибаться, но кажется, что когда отклонения нет, то здесь показывается время выполнения самого быстрого запроса)
Max - не разобрался пока (это точно не максимальное количество запросов в секунду! уверен!)
+/- Stdev - процент времени, когда число запросов в секунду находилось в пределах одного стандартного отклонения.
Transfer/sec - пропускная способность, например: 396.8 КБайт в секунду.
Приятно, что wrk поддерживает луа-скрипты, много примеров можно найти на странице гитхаба.
Очень удобно отслеживать параллельность запросов с помощью log_format в nginx.
А еще кто-то научился писать полные ответы от сервера.
p.s. всякие мои тесты, не обращайте внимание:
| Параметры | Кол-во запросов, которые делает wrk, если php-fpm обрабатывает запрос мгновенно | Кол-во запросов, которые делает wrk, если php-fpm обрабатывает запрос за 1 секунд. Повезло / не повезло - означает, что могло быть иначе, причина в том, отключится ли wrk от nginx в течении секунды или нет. | Кол-во запросов, которые делает wrk, если php-fpm обрабатывает запрос за 8 секунд |
| -t1 -c1 -d2s | 3 | 1 успешный + 1 успешный (повезло) | 1 неуспешный |
| -t1 -c2 -d1s | 4 | 2 успешных (повезло) | 2 неуспешных |
| -t1 -c2 -d2s | 4 | 2 успешных + 2 успешных | 2 неуспешных |
| -t1 -c2 -d10s | 4 | 2 успешных + 2 успешных | 2 успешных + 2 неуспешных |
| -t1 -c3 -d1s | 5 | 3 неуспешных (не повезло) | 3 неуспешных |
| -t1 -c3 -d10s | 5 | 2 успешных + 2 успешных + 1 успешный | 3 успешных + 2 неуспешных |
| -t1 -c9 -d1s | 11 | запустил 3 раза и получил по разному: - одновременно: 3 успешных и 6 неуспешных | 9 неуспешных |
| -t1 -c9 -d10s | 11 | 9 успешных (повезло) + 2 неуспешных | 9 (2 усп + 7 неусп) + 2 неуспешных |
| -t1 -c9 -d100s | 11 | 11 успешных | 11 успешных |