wrk(1)- 詳細使用

小菠蘿測試筆記發表於2021-06-10

背景

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

相關文章