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執行環境
啟動階段
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`,返回 true 或 false
function wrk.connect(addr)
複製程式碼