背景
- 公司對 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 核數是一個比較靠譜的建議