背景
- 公司對 http 介面都是直接用 wrk 進行壓測,簡單快捷
- 剛好有個壓測任務分到我
- 而且中臺跟 Lua 也有關係,剛好 wrk 也支援 Lua 指令碼,所以學起來,再用起來
介紹
- wrk 是一個類似 ab(apache bench)、jmeter 的壓力測試工具,官方稱它為:現代的 HTTP 基準測試工具
- 用 C 編寫的 HTTP 協議壓測工具
- 底層基於 epoll 和 kqueue 實現,使用了多執行緒和多路複用 IO(非阻塞 IO),利用非同步的事件驅動框架,通過很少的執行緒就可以壓出很大的併發量
- 降低測試工具本身效能開銷對測試結果準確性的影響
- 支援使用 LuaJIT 指令碼,可以執行 HTTP 請求生成、響應處理和自定義報告
它的定位
- 輕量級效能測試工具
- 僅支援 HTTP 協議
- 僅支援單機壓測,多機器壓測需要每個機器都手動執行一次 wrk 命令
- 不可取代 Jmeter、LR 等專業效能工具
架構&簡單原始碼解析
- 在 wrk 裡面,每個執行緒都有自己獨立的 Lua 虛擬機器和 Event Loop
- 通過命令列引數 -c 指定的連線數,會平均分給所有執行緒,每個新建的 socket,都會呼叫 fcntl 將其設定為 NONBLOCK,即非阻塞,然後託管給 Event Loop
- 直接使用 redis 的 Event Loop 實現,適配了不同作業系統的實現
- 啟動的時候,每個執行緒都會新建一個 Lua State,並呼叫 luaL_dofile 載入命令列引數 -s 指定的 lua 指令碼檔案
- 如果沒有自定義的 lua 指令碼,wrk 預設傳送的是 HTTP 1.1 GET 請求,用長連線
語法格式
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)
引數說明
- -c:與伺服器保持的 http 連線數
- -d:壓測持續執行時間,可以是 2s、2m、2h
- -t:啟動的執行緒數
- -s:指定 lua 指令碼
- -H:自定義 http header 請求頭,例如:"User-Agent: benchmark-wrk"
- --latency:列印延遲統計資料
- --time:http 超時時間,如果在此時間內未收到響應,則當做超時
數字引數:可以使用 1k、1M、1G 單位
-t
- 一般是 CPU 核數,最大不要超過 CPUx2 核數,否則會帶來額外的上下文切換,將執行緒數設定為 CPU 核數主要是為了 WRK 能最大化利用 CPU,使結果更準確(擷取網上,暫時沒看到官方推薦)
- 和併發數沒有直接關係
- 檢視 Linux CPU 總核數:
grep processor /proc/cpuinfo |wc -l
-c
- 連線數(connection)可以理解為併發數
- 一般在測試過程中,這個值需要使用者不斷向上除錯,直至 QPS 達到一個臨界點,便可認為此時的併發數為系統所能承受的最大併發量
- 實際上,wrk 會為每個執行緒分配(c/t)個 socket 連線
- 每個連線會先執行請求動作,然後等待直到收到響應後才會再傳送請求,所以每個時間點的併發數大致等於連線數(connection)
官方 Tips
- 執行 wrk 的機器必須有足夠數量的臨時埠可用,關閉的 socket 必須快速回收
- 僅更改 HTTP 方法、路徑、新增請求頭或正文的使用者指令碼不會對效能產生影響
- 每個請求的操作,特別是構建新的 HTTP 請求,以及 response() 的使用將必然減少可以生成的負載量
簡單栗子
啟動 2 個執行緒,保持 5 個 http 連線開啟的狀態下,持續壓測 10s 的基準測試
wrk -t2 -c5 -d10s https://httpbin.org/get
qps 是 14.85
啟動 16 個執行緒,保持 400 個 http 連線開啟的狀態下,持續壓測 5s 的基準測試,並列印延遲統計資料
wrk -t16 -c400 -d5s --latency https://httpbin.org/get
qps 是 578.7
結果解析
Running 5s test @ https://httpbin.org/get 壓測時間5s 16 threads and 400 connections 共16個測試執行緒,400個連線,和上引數設定一樣 Thread Stats Avg Stdev Max +/- Stdev 平均值 標準差 最大值 正負標準差的範圍,越大表示值和平均值不會差很多,離散也不大,表示 Avg 相對可信 Latency 311.74ms 211.97ms 1.57s 90.79% 延遲 Req/Sec 47.86 31.17 170.00 66.79% 每個執行緒每秒的完成的請求數 Latency Distribution 延遲分佈 50% 234.77ms 75% 244.43ms 90% 402.99ms 99% 1.26s 99% 的請求在 1.26s 內完成 2938 requests in 5.08s, 1.21MB read 5.08 s內共處理完成了 2938 個請求,讀取了 1.21MB 資料 Socket errors: connect 166, read 0, write 0, timeout 1 Socket 成功連線 166個,超時 1 個 Requests/sec: 578.70 平均每秒處理完成 578.7 個請求,QPS=578.7 Transfer/sec: 243.05KB 平均每秒讀取資料 243.05KB
-t 的一些實驗
測試資源
- 施壓機:16c32g
- 受壓機:8c16g
接下來對某個介面進行基準測試
16 個執行緒,400個併發量,持續執行 5min
qps:20504.3
64 個執行緒,400個併發量,持續執行 5min
qps:19948.69
128 個執行緒,400個併發量,持續執行 5min
qps:18811.35
結論
- 執行緒數增加,qps 反而下降
- 初步可以認為,-t 執行緒數取系統 CPU 核數是一個比較靠譜的建議