nodejs-壓力測試

wrk是一個用來做HTTP benchmark測試的工具??梢援a(chǎn)生顯著的壓力。
相比于Apache ab功能更為強(qiáng)大,可以使用lua腳本來支持更為復(fù)雜的測試場景,例如PUT請求等。在對于Restful架構(gòu)的API接口來說,測試起來更加便捷。

源碼地址: https://github.com/wg/wrk

brew install wrk

基本使用

命令行敲下wrk,可以看到使用幫助

使用方法: wrk <選項> <被測HTTP服務(wù)的URL>                            
  Options:                                            
    -c, --connections <N>  跟服務(wù)器建立并保持的TCP連接數(shù)量  
    -d, --duration    <T>  壓測時間           
    -t, --threads     <N>  使用多少個線程進(jìn)行壓測   
                                                      
    -s, --script      <S>  指定Lua腳本路徑       
    -H, --header      <H>  為每一個HTTP請求添加HTTP頭      
        --latency          在壓測結(jié)束后,打印延遲統(tǒng)計信息   
        --timeout     <T>  超時時間     
    -v, --version          打印正在使用的wrk的詳細(xì)版本信息
                                                      
  <N>代表數(shù)字參數(shù),支持國際單位 (1k, 1M, 1G)
  <T>代表時間參數(shù),支持時間單位 (2s, 2m, 2h)
  1. 做一次簡單壓測,分析下結(jié)果
wrk -t8 -c200 -d30s --latency  "http://www.bing.com"

以上使用8個線程200個連接,對bing首頁進(jìn)行了30秒的壓測,并要求在壓測結(jié)果中輸出響應(yīng)延遲信息。以下對壓測結(jié)果進(jìn)行簡單注釋:

Running 30s test @ http://www.bing.com (壓測時間30s)
  8 threads and 200 connections (共8個測試線程,200個連接)
  Thread Stats   Avg      Stdev     Max   +/- Stdev
              (平均值) (標(biāo)準(zhǔn)差)(最大值)(正負(fù)一個標(biāo)準(zhǔn)差所占比例)
    Latency    46.67ms  215.38ms   1.67s    95.59%
    (延遲)
    Req/Sec     7.91k     1.15k   10.26k    70.77%
    (處理中的請求數(shù))
  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秒內(nèi)共處理完成了1790465個請求,讀取了684.08MB數(shù)據(jù))
Requests/sec:  59658.29 (平均每秒處理完成59658.29個請求)
Transfer/sec:     22.79MB (平均每秒讀取數(shù)據(jù)22.79MB)

可以看到,wrk使用方便,結(jié)果清晰。并且因為非阻塞IO的使用,可以在普通的測試機(jī)上創(chuàng)建出大量的連接,從而達(dá)到較好的壓測效果。

使用Lua腳本個性化wrk壓測

以上兩節(jié)安裝并簡單使用了wrk,但這種簡單的壓測可能不能滿足我們的需求。比如我們可能需要使用POST METHOD跟服務(wù)器交互;可能需要為每一次請求使用不同的參數(shù),以更好的模擬服務(wù)的實際使用場景等。wrk支持用戶使用–script指定Lua腳本,來定制壓測過程,滿足個性化需求。

1.介紹wrk對Lua腳本的支持
wrk支持在三個階段對壓測進(jìn)行個性化,分別是啟動階段、運行階段和結(jié)束階段。每個測試線程,都擁有獨立的Lua運行環(huán)境。

2.啟動階段

function setup(thread)

在腳本文件中實現(xiàn)setup方法,wrk就會在測試線程已經(jīng)初始化但還沒有啟動的時候調(diào)用該方法。wrk會為每一個測試線程調(diào)用一次setup方法,并傳入代表測試線程的對象thread作為參數(shù)。setup方法中可操作該thread對象,獲取信息、存儲信息、甚至關(guān)閉該線程。

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

3.運行階段

function init(args)
function delay()
function request()
function response(status, headers, body)

init由測試線程調(diào)用,只會在進(jìn)入運行階段時,調(diào)用一次。支持從啟動wrk的命令中,獲取命令行參數(shù); delay在每次發(fā)送request之前調(diào)用,如果需要delay,那么delay相應(yīng)時間; request用來生成請求;每一次請求都會調(diào)用該方法,所以注意不要在該方法中做耗時的操作; reponse在每次收到一個響應(yīng)時調(diào)用;為提升性能,如果沒有定義該方法,那么wrk不會解析headers和body;

4.結(jié)束階段

function done(summary, latency, requests)

該方法在整個測試過程中只會調(diào)用一次,可從參數(shù)給定的對象中,獲取壓測結(jié)果,生成定制化的測試報告。

自定義腳本中可訪問的變量和方法
變量: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.
    根據(jù)參數(shù)和全局變量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),返回所有可用的服務(wù)器地址信息。

  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().
    測試與給定的服務(wù)器地址信息是否可以成功創(chuàng)建連接

示例

  1. 使用POST METHOD
// 通過修改全局變量wrk,使得所有請求都使用POST方法,并指定了body和Content-Type頭。
wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
  1. 為每次request更換一個參數(shù)
// 通過在request方法中隨機(jī)生成1~10000000之間的uid,使得請求中的uid參數(shù)隨機(jī)。
request = function()
   uid = math.random(1, 10000000)
   path = "/test?uid=" .. uid
   return wrk.format(nil, path)
end
  1. 每次請求之前延遲10ms
function delay()
   return 10
end
  1. 每個線程要先進(jìn)行認(rèn)證,認(rèn)證之后獲取token以進(jìn)行壓測
// 在沒有token的情況下,先訪問/authenticate認(rèn)證。認(rèn)證成功后,讀取token并替換path為/resource。
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
  1. 壓測支持HTTP pipeline的服務(wù)
// 通過在init方法中將三個HTTP request請求拼接在一起,實現(xiàn)每次發(fā)送三個請求,以使用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

http://zhaox.github.io/benchmark/2016/12/28/wrk-guidelines

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容