天天看點

WRK:一個可程式設計的HTTP性能測試工具

同 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 監控了一下請求:

WRK:一個可程式設計的HTTP性能測試工具

ngrep -W byline ” ‘dst port 80’

如圖可見,wrk 随機發送了不同的請求,完美!