"подготовить официальное представление": wrk это современный HTTP Инструмент для тестирования производительности, способный запускать несколько ядер на одном CPU Создает большую нагрузку при работе. Он сочетает в себе многопоточный дизайн с масштабируемой системой уведомлений о событиях, такой как epoll и kqueue) вместе взятые. Необязательный LuaJIT Скрипт может быть выполнен HTTP Генерация запросов, обработка ответов и настраиваемые отчеты. Подробности доступны на SCRIPTING Найдено в , несколько примеров находятся в scripts/ середина.
wrk --help
[windealli@VM-52-29-centos workspace]$ wrk --help
Usage: wrk <options> <url>
Options:
-c, --connections <N> Connections to keep open Количество соединений
-d, --duration <T> Duration of test Время испытания давлением
-t, --threads <N> Number of threads to Использование открывает количество потоков
-s, --script <S> Load Lua script file Используйте Lua-скрипт
-H, --header <H> Add header to request
--latency Print latency statistics
--timeout <T> Socket/request timeout
-v, --version Print version details
Numeric arguments may include a SI unit (1k, 1M, 1G)
Time arguments may include a time unit (2s, 2m, 2h)
Примеры ниже,использоватьwrkЗаказверноhttp://127.0.0.1:80/sayHello?power=10
Провести стресс-тестирование。
wrk -t12 -c1000 -d30s http://127.0.0.1:80/sayHello?power=10
в:
-t12
: Указывает, что клиент запустил 12 потоков для стресс-тестирования.
-c1000
: Показывает, что открыто 1000 соединений.
-d30s
: Указывает, что время испытания давлением составляет 30 с.
[windealli@VM-52-29-centos workspace]$ wrk -t12 -c1000 -d30s http://127.0.0.1:80
/sayHello?power=10
Running 30s test @ http://119.91.66.202/sayHello?power=10
12 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 172.14ms 317.41ms 1.99s 92.37%
Req/Sec 88.75 96.55 2.39k 91.91%
29616 requests in 30.10s, 36.59MB read
Socket errors: connect 0, read 0, write 0, timeout 1278
Requests/sec: 983.92
Transfer/sec: 1.22MB
[windealli@VM-52-29-centos workspace]$
Описание результатов:
В ходе 30-секундного стресс-теста было инициировано в общей сложности 29 616 запросов и прочитано 36,59 МБ данных.
Среднее количество запросов в секунду 983,92,Requests/sec: 983.92
Средняя задержка: 172,14 мс, максимальная задержка 1,99 с.
wrk поддерживает написание сценариев на основе luaJIT для реализации сложных тестов производительности.
Официальная документацияwrk/SCRIPTINGпредставить свойиспользоватьметод。
Возможности создания сценариев wrk можно свести к следующим частям:
wrk
wrk.format()
,wrk.lookup()
,wrk.connect
в работе,Интерфейс разработки,глобальнымtable
иглобальный наборфункциякомпозиция:
wrk
wrk = {
scheme = "http",
host = "localhost",
port = nil,
method = "GET",
path = "/",
headers = {},
body = nil,
thread = <userdata>,
}
function wrk.format(method, path, headers, body)
-- wrk.format Создайте http-запрос на основе входных параметров. Присоединяйтесь к встрече и работайте над глобальной таблицейслить,
-- @param method : http method, Такие как POST, GET
-- @param method : запрошенный путь
-- @parma headers : Запросить заголовки для переноса, это стол
-- @param body : Тело запроса пакета
-- @return : Возвращает пакет запроса, который можно выбрать и использовать в request() при запускеэтапа.
function wrk.format(method, path, headers, body)
function wrk.lookup(host, service)
-- wrk.lookup : Возвращает всю согласованную адресную информацию согласно параметру хостисервис, Соответствует POSIX getaddrinfo() функция
function wrk.lookup(host, service)
function wrk.connect(addr)
-- wrk.connect : Проверьте, можно ли успешно подключить адрес addr.
-- @param addr : Целевой адрес для проверки должен быть адресом, возвращаемым wrk.lookup.
-- @return : Если соединение успешное, оно возвращает true, в противном случае — false.
function wrk.connect(addr)
wrk поддерживает запуск сценариев luaJIT на следующих трех этапах:
каждыйэтап Некоторые соответствующиефункцияинтерфейс,Эти интерфейсы будут вызываться на соответствующем этапе при запуске теста wrk.
setup
иdone
этап работает в независимой скриптовой среде и не участвует вrunning
процесс. Таким образом, глобальные переменные не являются общими.
setup
этапsetupэтап Он начинается, когда анализируется IP-адрес назначения, и заканчивается, когда тестовый поток инициализируется (но еще не запускается).
В настройкеэтап согласовали интерфейс
-- setup Вызывается каждый раз при запуске потока.
-- @param thread Объект пользовательских данных, используемый для представления текущего потока.
function setup(thread)
thread.addr -- get or set the thread's server address
thread:get(name) -- Получите значение из переменной среды потока.
thread:set(name, value) -- Установите переменные среды для потоков,
thread:stop() -- Остановите ветку.
потому чтоfunction setup(thread)
находится вsetupэтапвызов,При запускеэтап в автономной среде сценариев середина.
На этот раз разные потоки используют общие глобальные переменные. Мы можем пронумеровать каждого здесь.
running
этапrunning
этап Инициализация из потокаinit()
начинать,Затем повторитеrequest()
иresponse()
цикл
running
этап Было согласовано следующеефункцияинтерфейс:
-- init Инициализация потока
-- @param args Используется для получения параметров строки заказа, переданных пользователем.
function init(args)
-- delay Используется для указания времени задержки отправки следующего запроса.
-- @return Время задержки возврата, единица измерения — мс
function delay()
-- request Используется для создания текущего HTTP для отправки. request, С помощью запроса можно добиться эффекта разного контента для каждого запроса. Однако, поскольку при построении запроса возникают некоторые накладные расходы, тестирование лучше всего проводить путем предварительного создания пакета запроса в init()этап (через wrk.format()), а затем быстрого опроса/выбора там.
-- @return HTTP для отправки request
function request()
-- response Этот метод вызывается, когда wrk получает ответ на запрос, где можно выполнить статистику и анализ ответа.
-- @param status : Код состояния HTTP
-- @param headers : заголовки ответов
-- @param body : тело ответа
function response(status, headers, body)
done
этапКогда работа каждого теста потока завершена (время заканчивается), начинается этот этап.
done
этап Договорились о следующеминтерфейс
-- done Тест завершается вызовом, а на основе входных параметров осуществляется анализ данных и отображение этого бенчмарк-теста.
-- @params summary : Сводка результатов тестирования (общее количество запросов, различные индикаторы ошибок и т. д.)
-- @params latency : Сводная информация о задержке. (максимальная задержка, минимальная задержка, средняя задержка и т. д.)
-- @params requests : Сводка результатов испытаний
function done(summary, latency, requests)
-- post.lua
wrk.method="POST"
wrk.headers["Content-Type"] = "application/json"
wrk.body = "{\"UserId\":1001}"
wrk -t2 -c1000 -d10s -s test.lua http://127.0.0.1:8080/sayHello
Тестовый скрипт:
local index = 0
function init(args)
-- Создайте 4 разных запроса
req = {}
req[0] = wrk.format("GET", "/?userId=1001", nil, nil)
req[1] = wrk.format("GET", "/?userId=1002", nil, nil)
end
function request()
index = index + 1
return req[index%2]
end
Тестовая команда:
wrk -t2 -c1000 -d10s -s test.lua http://127.0.0.1:8080/
Серверная программа, написанная на go:
package main
import (
"fmt"
"net/http"
)
func handle(w http.ResponseWriter, r *http.Request) {
userId := r.URL.Query().Get("userId")
fmt.Printf("userId: %s\n", userId)
w.Write([]byte("hello " + userId))
// return
}
func main() {
http.HandleFunc("/", handle)
fmt.Println("http server start, :8080")
http.ListenAndServe(":8080", nil)
}
Скрипт стресс-теста
local count_thread = 0
local threads = {}
function setup(thread)
thread:set("id", count_thread)
table.insert(threads, thread)
count_thread = count_thread + 1
end
function init(args)
res_a = 0
res_b = 0
end
function response(status, headers, body)
if body == "a"
then
res_a = res_a + 1
else
res_b = res_b + 1
end
end
-- Подсчитайте количество ответов «а» и «б»
function done(summary, latency, requests)
for index, thread in ipairs(threads) do
local res_a = thread:get("res_a") -- Получите значение переменной res_a потока.
local res_b = thread:get("res_b")
print("res_a: " .. res_a)
print("res_b: " .. res_b)
end
end
Серверная программа, написанная на Go:
func handle(w http.ResponseWriter, r *http.Request) {
if time.Now().Unix()%5 == 0 {
w.Write([]byte("a"))
} else {
w.Write([]byte("b"))
}
}
func main() {
http.HandleFunc("/", handle)
fmt.Println("http server start, :8080")
http.ListenAndServe(":8080", nil)
}
Посмотреть результаты теста,можно увидетьb
Количество ответов’a‘из4О временах,Как и ожидалось.
➜ wrk git:(main) ✗ wrk -t2 -c1000 -d10s -s test.lua http://127.0.0.1:8080/
Running 10s test @ http://127.0.0.1:8080/
2 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.92ms 3.79ms 39.29ms 74.21%
Req/Sec 47.40k 13.73k 126.56k 82.63%
921607 requests in 10.05s, 102.83MB read
Socket errors: connect 0, read 1023, write 80, timeout 0
Requests/sec: 91722.38
Transfer/sec: 10.23MB
res_a: 92497
res_b: 372194
res_a: 93570
res_b: 363346
➜ wrk git:(main) ✗