當前位置: 妍妍網 > 碼農

http壓測工具wrk是真的強~【附上使用指南】

2024-06-20碼農

關註上方 浩道Linux ,回復 資料 ,即可獲取海量 L inux Python 網路通訊、網路安全 等學習資料!

前言

大家好,這裏是 浩道Linux ,主要給大家分享 L inux P ython 網路通訊、網路安全等 相關的IT知識平台。

今天浩道跟大家分享一款http壓測工具,發現確實很強, 寫下這份使用指南給自己備忘用,如果能幫到你,那也很好。

文章來源:https://www.cnblogs.com/xinzhao/p/6233009.html

安裝

wrk支持大多數類UNIX系統,不支持windows。需要作業系統支持 LuaJIT 和OpenSSL,不過不用擔心,大多數類Unix系統都支持。安裝wrk非常簡單,只要從github上下載wrk源碼,在計畫路徑下執行make命令即可。

git clone https://github.com/wg/wrk
make

make之後,會在計畫路徑下生成可執行檔wrk,隨後就可以用其進行HTTP壓測了。可以把這個可執行檔拷貝到某個已在path中的路徑,比如/usr/local/bin,這樣就可以在任何路徑直接使用wrk了。

預設情況下wrk會使用內建的LuaJIT和OpenSSL,如果你想使用系統已安裝的版本,可以使用WITH_LUAJIT和WITH_OPENSSL這兩個選項來指定它們的路徑。比如:

make WITH_LUAJIT=/usr WITH_OPENSSL=/usr

基本使用

  1. 命令列敲下wrk,可以看到使用幫助

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 use
-s, --script <S> Load Lua script file
-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服務的URL>
Options:
-c, --connections <N> 跟伺服器建立並保持的TCP連線數量
-d, --duration <T> 壓測時間
-t, --threads <N> 使用多少個執行緒進行壓測
-s, --script <S> 指定Lua指令碼路徑
-H, --header <H> 為每一個HTTP請求添加HTTP頭
--latency 在壓測結束後,打印延遲統計資訊
--timeout <T> 超時時間
-v, --version 打印正在使用的wrk的詳細版本資訊
<N>代表數位參數,支持國際單位 (1k, 1M, 1G)
<T>代表時間參數,支持時間單位 (2s, 2m, 2h)

  1. 看下版本

wrk -v
輸出:
wrk 4.0.2[epoll] Copyright (C) 2012 Will Glozer

看到是4.0.2版本的wrk,使用了epoll。這意味著我們可以用少量的執行緒來跟被測服務建立大量連線,進行壓測。

  1. 做一次簡單壓測,分析下結果

wrk -t8 -c200 -d30s --latency "http://www.bing.com"
輸出:
Running 30s test @ http://www.bing.com
8 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 46.67ms 215.38ms 1.67s 95.59%
Req/Sec 7.91k 1.15k 10.26k 70.77%
Latency Distribution
50% 2.93ms
75% 3.78ms
90% 4.73ms
99% 1.35s
1790465 requests in 30.01s, 684.08MB read
Requests/sec: 59658.29
Transfer/sec: 22.79MB

以上使用8個執行緒200個連線,對bing首頁進行了30秒的壓測,並要求在壓測結果中輸出響應延遲資訊。以下對壓測結果進行簡單註釋:

Running 30s test @ http://www.bing.com (壓測時間30s)
8 threads and 200 connections (共8個測試執行緒,200個連線)
Thread Stats Avg Stdev Max +/- Stdev
(平均值) (標準差)(最大值)(正負一個標準差所占比例)
Latency 46.67ms 215.38ms 1.67s 95.59%
(延遲)
Req/Sec 7.91k 1.15k 10.26k 70.77%
(處理中的請求數)
Latency Distribution (延遲分布)
50% 2.93ms
75% 3.78ms
90% 4.73ms
99% 1.35s (99分位的延遲)
1790465 requests in 30.01s, 684.08MB read (30.01秒內共處理完成了1790465個請求,讀取了684.08MB數據)
Requests/sec: 59658.29 (平均每秒處理完成59658.29個請求)
Transfer/sec: 22.79MB (平均每秒讀取數據22.79MB)

可以看到,wrk使用方便,結果清晰。並且因為非阻塞IO的使用,可以在普通的測試機上建立出大量的連線,從而達到較好的壓測效果。

使用Lua指令碼個人化wrk壓測

以上兩節安裝並簡單使用了wrk,但這種簡單的壓測可能不能滿足我們的需求。比如我們可能需要使用POST METHOD跟伺服器互動;可能需要為每一次請求使用不同的參數,以更好的模擬服務的實際使用場景等。wrk支持使用者使用--script指定Lua指令碼,來客製壓測過程,滿足個人化需求。

  1. 介紹wrk對Lua指令碼的支持

wrk支持在三個階段對壓測進行個人化,分別是啟動階段、執行階段和結束階段。每個測試執行緒,都擁有獨立的Lua執行環境。

啟動階段

functionsetup(thread)

在指令碼檔中實作setup方法,wrk就會在測試執行緒已經初始化但還沒有啟動的時候呼叫該方法。wrk會為每一個測試執行緒呼叫一次setup方法,並傳入代表測試執行緒的物件thread作為參數。setup方法中可操作該thread物件,獲取資訊、儲存資訊、甚至關閉該執行緒。

thread.addr - getorset the thread's server address
thread:get(name) - get the value of a globalin the thread's env
thread:set(name, value) - set the value of a globalin the thread's env
thread:stop() - stop the thread

執行階段

functioninit(args)
functiondelay()
functionrequest()
functionresponse(status, headers, body)

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

結束階段

functiondone(summary, latency, requests)

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

自訂指令碼中可存取的變量和方法

變量:wrk

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

一個table型別的變量wrk,是全域變量,修改該table,會影響所有請求。

方法:wrk.fomat wrk.lookup wrk.connect

function wrk.format(method, path, headers, body)
wrk.format returns a HTTP request string containing the passed parameters
merged withvaluesfrom the wrk table.
根據參數和全域變量wrk,生成一個HTTP rquest string。
function wrk.lookup(host, service)
wrk.lookup returns a table containing all known addresses for the host
and service pair. This corresponds to the POSIX getaddrinfo() function.
給定host和service(port/well known service name),返回所有可用的伺服器地址資訊。
function wrk.connect(addr)
wrk.connect returnstrue if the address can be connected to, otherwise
it returns false. The address must be one returned from wrk.lookup().
測試與給定的伺服器地址資訊是否可以成功建立連線



  1. 範例

使用POST METHOD

wrk.method = "POST"
wrk.body = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

透過修改全域變量wrk,使得所有請求都使用POST方法,並指定了body和Content-Type頭。

為每次request更換一個參數

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

透過在request方法中隨機生成1~10000000之間的uid,使得請求中的uid參數隨機。

每次請求之前延遲10ms

functiondelay()
return10
end

每個執行緒要先進行認證,認證之後獲取token以進行壓測

token = nil
path = "/authenticate"
request = function()
return wrk.format("GET", path)
end
response = function(status, headers, body)
ifnot token andstatus == 200then
token = headers["X-Token"]
path = "/resource"
wrk.headers["X-Token"] = token
end
end

在沒有token的情況下,先存取/authenticate認證。認證成功後,讀取token並替換path為/resource。

壓測支持HTTP pipeline的服務

init = function(args)
local r = {}
r[1] = wrk.format(nil, "/?foo")
r[2] = wrk.format(nil, "/?bar")
r[3] = wrk.format(nil, "/?baz")
req = table.concat(r)
end
request = function()
return req
end

透過在init方法中將三個HTTP request請求拼接在一起,實作每次發送三個請求,以使用HTTP pipeline。

最後

源碼非常簡潔,簡單讀了讀,很佩服wrk的作者。

更多精彩

關註公眾號 浩道Linux

浩道Linux ,專註於 Linux系統 的相關知識、 網路通訊 網路安全 Python相關 知識以及涵蓋IT行業相關技能的學習, 理論與實戰結合,真正讓你在學習工作中真正去用到所學。同時也會分享一些面試經驗,助你找到高薪offer,讓我們一起去學習,一起去進步,一起去漲薪!期待您的加入~~~ 關註回復「資料」可 免費獲取學習資料 (含有電子書籍、視訊等)。

喜歡的話,記得 點「贊」 「在看」