http 效能測試 wrk使用教程

ckshop發表於2018-01-14

wrk是一個http的壓測工具,底層封裝了epoll(linux)和kqueue(bsd),所以效能特別好

安裝

Unbuntu/Debian下的安裝

sudo apt-get install build-essential libssl-dev git -y
git clone https://github.com/wg/wrk.git wrk
cd wrk
make
# 把生成的wrk移到一個PATH目錄下面, 比如
sudo cp wrk /usr/local/bin
複製程式碼

CentOs/RedHat/Fedora

sudo yum groupinstall 'Development Tools'
sudo yum install openssl-devel
sudo yum install git
git clone https://github.com/wg/wrk.git wrk
cd wrk
make
# 把生成的wrk移到一個PATH目錄下面, 比如
sudo cp wrk /usr/local/bin
複製程式碼

基本壓測

wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html

使用12個執行緒執行30秒, 400個http併發

命令列選項

-c, --connections: 總的http併發數

-d, --duration:    持續壓測時間, 比如: 2s, 2m, 2h

-t, --threads:     匯流排程數

-s, --script:      luajit指令碼,使用方法往下看

-H, --header:      新增http header, 比如. "User-Agent: wrk"

    --latency:     在控制檯列印出延遲統計情況

    --timeout:     http超時時間
複製程式碼

lua指令碼壓測

在基本壓測中, 每次傳送的請求都是一樣的,很多時候我們壓測的請求體是每個請求都不一樣, 這時候就要寫lua基本來壓測

使用POST方法壓測

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
複製程式碼
wrk -t2 -d30s -c1k -s xxx.lua http://192.168.17.1/
複製程式碼

每個request的引數都不一樣

request = function()
   uid = math.random(1, 10000000)
   path = "/test?uid=" .. uid
   return wrk.format(nil, path)
end
複製程式碼

解釋一下wrk.format這個函式

wrk.format這個函式的作用,根據引數和全域性變數wrk生成一個http請求
函式簽名: function wrk.format(method, path, headers, body)
method:http方法,比如GET/POST等
path: url上的路徑(含函式)
headers: http header
body: http body
複製程式碼

每個執行緒先登入然後壓測

token = nil
path  = "/authenticate"

request = function()
   return wrk.format("GET", path)
end

response = function(status, headers, body)
   if not token and status == 200 then
      token = headers["X-Token"]
      path  = "/resource"
      wrk.headers["X-Token"] = token
   end
end
複製程式碼

傳送json

request = function()
    local headers = { }
    headers['Content-Type'] = "application/json"
    body = {
        mobile={"1533899828"},
        params={code=math.random(1000,9999)}
    }

    local cjson = require("cjson")
    body_str = cjson.encode(body)
    return wrk.format('POST', nil, headers, body_str)
end
複製程式碼

若執行的時候報錯找不到cjson, 可以安裝 luarocks install lua-cjson

wrk lua指令碼說明

wrk 壓測指令碼有3個生命週期, 分別是 啟動階段,執行階段和結束階段,每個執行緒都有自己的lua執行環境

image

啟動階段

function setup(thread)
在指令碼檔案中實現setup方法,wrk就會在測試執行緒已經初始化但還沒有啟動的時候呼叫該方法。wrk會為每一個測試執行緒呼叫一次setup方法,並傳入代表測試執行緒的物件thread作為引數。setup方法中可操作該thread物件,獲取資訊、儲存資訊、甚至關閉該執行緒。
-- thread提供了1個屬性,3個方法
-- thread.addr 設定請求需要打到的ip
-- thread:get(name) 獲取執行緒全域性變數
-- thread:set(name, value) 設定執行緒全域性變數
-- thread:stop() 終止執行緒
複製程式碼

執行階段

function init(args)
-- 每個執行緒僅呼叫1次,args 用於獲取命令列中傳入的引數, 例如 --env=pre

function delay()
-- 每次請求呼叫1次,傳送下一個請求之前的延遲, 單位為ms

function request()
-- 每次請求呼叫1次,返回http請求

function response(status, headers, body)
-- 每次請求呼叫1次,返回http響應

複製程式碼

init由測試執行緒呼叫,只會在進入執行階段時,呼叫一次。支援從啟動wrk的命令中,獲取命令列引數; delay在每次傳送request之前呼叫,如果需要delay,那麼delay相應時間; request用來生成請求;每一次請求都會呼叫該方法,所以注意不要在該方法中做耗時的操作; reponse在每次收到一個響應時呼叫;為提升效能,如果沒有定義該方法,那麼wrk不會解析headers和body; 結束階段

結束階段

function done(summary, latency, requests)


latency.min              -- minimum value seen
latency.max              -- maximum value seen
latency.mean             -- average value seen
latency.stdev            -- standard deviation
latency:percentile(99.0) -- 99th percentile value
latency(i)               -- raw value and count

summary = {
  duration = N,  -- run duration in microseconds
  requests = N,  -- total completed requests
  bytes    = N,  -- total bytes received
  errors   = {
    connect = N, -- total socket connection errors
    read    = N, -- total socket read errors
    write   = N, -- total socket write errors
    status  = N, -- total HTTP status codes > 399
    timeout = N  -- total request timeouts
  }
}
複製程式碼

該方法在整個測試過程中只會呼叫一次,可從引數給定的物件中,獲取壓測結果,生成定製化的測試報告。

執行緒變數

wrk = {
    scheme  = "http",
    host    = "localhost",
    port    = nil,
    method  = "GET",
    path    = "/",
    headers = {},
    body    = nil,
    thread  = <userdata>,
}

-- 生成整個request的string,例如:返回
-- GET / HTTP/1.1
-- Host: tool.lu
function wrk.format(method, path, headers, body)
-- method: http方法, 如GET/POST/DELETE 等
-- path:   url的路徑, 如 /index, /index?a=b&c=d
-- headers: 一個header的table
-- body:    一個http body, 字串型別

-- 獲取域名的IP和埠,返回table,例如:返回 `{127.0.0.1:80}`
function wrk.lookup(host, service)
-- host:一個主機名或者地址串(IPv4的點分十進位制串或者IPv6的16進位制串)
-- service:服務名可以是十進位制的埠號,也可以是已定義的服務名稱,如ftp、http等


-- 判斷addr是否能連線,例如:`127.0.0.1:80`,返回 truefalse
function wrk.connect(addr)
複製程式碼

相關文章