Http壓測工具wrk使用指南

用過了不少壓測工具,卻一直沒找到中意的那款。最近試了wrk感受不錯,寫下這份使用指南給本身備忘用,若是能幫到你,那也很好。git

安裝

wrk支持大多數類UNIX系統,不支持windows。須要操做系統支持LuaJIT和OpenSSL,不過不用擔憂,大多數類Unix系統都支持。安裝wrk很是簡單,只要從github上下載wrk源碼,在項目路徑下執行make命令便可。github

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

make

make以後,會在項目路徑下生成可執行文件wrk,隨後就能夠用其進行HTTP壓測了。能夠把這個可執行文件拷貝到某個已在path中的路徑,好比/usr/local/bin,這樣就能夠在任何路徑直接使用wrk了。windows

默認狀況下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)

簡單翻成中文:app

使用方法: 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。這意味着咱們能夠用少許的線程來跟被測服務建立大量鏈接,進行壓測。dom

  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的使用,能夠在普通的測試機上建立出大量的鏈接,從而達到較好的壓測效果。post

使用Lua腳本個性化wrk壓測

以上兩節安裝並簡單使用了wrk,但這種簡單的壓測可能不能知足咱們的需求。好比咱們可能須要使用POST METHOD跟服務器交互;可能須要爲每一次請求使用不一樣的參數,以更好的模擬服務的實際使用場景等。wrk支持用戶使用--script指定Lua腳本,來定製壓測過程,知足個性化需求。性能

  1. 介紹wrk對Lua腳本的支持

wrk支持在三個階段對壓測進行個性化,分別是啓動階段、運行階段和結束階段。每一個測試線程,都擁有獨立的Lua運行環境。測試

啓動階段
function setup(thread)

在腳本文件中實現setup方法,wrk就會在測試線程已經初始化但尚未啓動的時候調用該方法。wrk會爲每個測試線程調用一次setup方法,並傳入表明測試線程的對象thread做爲參數。setup方法中可操做該thread對象,獲取信息、存儲信息、甚相當閉該線程。

thread.addr             - get or set the thread's server address
thread:get(name)        - get the value of a global in the thread's env
thread:set(name, value) - set the value of a global in the thread's env
thread:stop()           - stop the thread
運行階段
function init(args)
function delay()
function request()
function response(status, headers, body)

init由測試線程調用,只會在進入運行階段時,調用一次。支持從啓動wrk的命令中,獲取命令行參數;
delay在每次發送request以前調用,若是須要delay,那麼delay相應時間;
request用來生成請求;每一次請求都會調用該方法,因此注意不要在該方法中作耗時的操做;
reponse在每次收到一個響應時調用;爲提高性能,若是沒有定義該方法,那麼wrk不會解析headers和body;

結束階段
function done(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 with values from 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 returns true 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
function delay()
   return 10
end
每一個線程要先進行認證,認證以後獲取token以進行壓測
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

在沒有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的做者。

相關文章
相關標籤/搜索