同 ab 這種單線程 HTTP 性能測試工具相比,wrk 是一個足夠現代化的 HTTP 性能測試工具,最重要的特性是:它是可程式設計的,借助内嵌 lua,我們可以控制測試的全過程。
關于 wrk 中 lua 擴充的資料結構,可以參考官方源代碼中的 wrk.lua 檔案:
local wrk = {
scheme = "http",
host = "localhost",
port = nil,
method = "GET",
path = "/",
headers = {},
body = nil,
thread = nil,
}
複制
此外,還有一些鈎子方法可供使用:
- setup(thread):啟動階段執行,每個線程調用一次
- init(args):運作階段執行,每個線程調用一次
- delay(),運作階段執行,每個請求調用一次
- request(),運作階段執行,每個請求調用一次
- response(status, headers, body),運作階段執行,每個請求調用一次
- done(summary, latency, requests),結束階段執行,整個過程調用一次
多數情況下,我們隻要關注 request 鈎子方法即可,通過它我們可以自定義請求的各個參數,如果想要了解更多的用法,可以參考官方源代碼的 scripts 目錄。
讓我們動手實戰一下,假設一個網站,主要的請求有三種,分别是:
- /a:GET 請求,占比 20%
- /b:GET 請求,占比 30%
- /c:POST 請求,占比 50%
結合前面提到的 wrk 中 lua 擴充的相關知識,我們可以實作如下代碼:
-- benchmark.lua
math.randomseed(os.time())
local config = {
{num=20, path="/a"},
{num=30, method="get", path="/b"},
{num=50, method="post", path="/c", body="foo=x&bar=y"},
}
local requests = {}
for i, request in ipairs(config) do
if request.method then
request.method = string.upper(request.method)
end
for _ = 1, request.num do
requests[#requests + 1] = i
end
end
local length = #requests
for _ = 1, length do
local m, n = math.random(length), math.random(length)
requests[m], requests[n] = requests[n], requests[m]
end
local count = 0
function request()
local i = (count % length) + 1
local request = config[requests[i]]
count = count + 1
return wrk.format(
request.method,
request.path,
request.headers,
request.body
)
end
複制
代碼邏輯很簡單,無非就是根據配置資訊生成一個大數組,然後把資料随機化一下,每個請求來的時候,根據計數器直接給一條資料即可。
我在我的筆記本上以此腳本為例實際跑了一個 100 并發的例子,這裡有個題外話需要提一下,很多人做 benchmark 隻關注 rps,卻忽略了 latency,這是不嚴謹的,設想一個網站的 rps 資料很好,但是總有一定百分比的請求出現高 latency,依然是有問題的:
shell> wrk -c 100 -s ./benchmark.lua http://localhost
Running 10s test @ http://localhost
2 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 4.26ms 1.04ms 23.95ms 94.87%
Req/Sec 11.85k 662.52 13.08k 67.50%
235787 requests in 10.00s, 71.95MB read
Non-2xx or 3xx responses: 0
Requests/sec: 23573.71
Transfer/sec: 7.19MB
複制
在測試的時候我順手用 ngrep 監控了一下請求:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2Pn5GcuYGM0IDZykjMlhzYyMzY1gDZlNjN3IzMmNjM4gTMjJGZvwVNxkzNyMTNtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
ngrep -W byline ” ‘dst port 80’
如圖可見,wrk 随機發送了不同的請求,完美!