wrk 使用記錄及踩過的坑


    1.  wrk是什么?
      https://github.com/wg/wrk

      wrk 是一個非常小巧高效的開源性能測試工具,支持lua腳本來創建復雜的測試場景。wrk 的一個很好的特性就是能用很少的線程壓出很大的並發量, 原因是它使用了一些操作系統特定的高性能 I/O 機制, 比如 select, epoll, kqueue 等。
      PS, lua 腳本的介紹 (Lua 是一種輕量小巧的腳本語言,用標准C語言編寫並以源代碼形式開放, 其設計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能),換一句話說,如果大家玩過各類大型MMORPG,大型多人角色扮演在線游戲,有些游戲販子會叫賣的適用於 DPS 職業的輸出宏,一部分宏,就是用 lua 寫的,對於玩過游戲的人來說並不陌生。

    2. 如何使用 wrk ?
      a. 首先,從 github 下載源碼。
      git clone https://github.com/wg/wrk.git
      需要補充說明的是,wrk 只能運行在 Unix 類系統上,所以大家可以用 MAC 或者 測試環境中的虛擬機來操作。
      下載完成后,可以看到一個目錄,wrk,進入該目錄。
      b. wrk 是用 C 寫的一個小巧的工具,因此可以通過 make 進行編譯,編譯成功以后得到一個可執行文件 wrk
          編譯 wrk 的關機是系統已經安裝 openssl 庫,如果系統沒有默認安裝 openssl, 可以自行安裝,參考 sudo yum install openssl-devel 大部分操作系統應該是已經按照好了的

      c. 執行可執行文件,在 terminal  中執行 ./wrk --help 可以查看 wrk 的用法

      xieludeMacBook-Pro:wrk xielu$ ./wrk --help

      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 表示為保持連接狀態的連接數, -d 表示本次壓力測試的執行時間,單位可以為60s, 1m, 1h, -t 表示執行操作的線程數,-s 表示帶lua腳本執行,復雜測試場景,都是依賴 s 后的腳本編寫完成后執行的。
      --latency 延遲時間數據統計。

    3. lua 腳本編寫。
      cd scripts ,可以看到很多 wrk 的腳本,使用 post.lua 作為例子。
      原版的 post.lua 內容:

      -- example HTTP POST script which demonstrates setting the
      -- HTTP method, body, and adding a header

      wrk.method = "POST"
      wrk.body = "foo=bar&baz=quux"
      wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"


      做過 http 接口測試的同學應該很熟悉,這里描述了一個非常簡單的 POST 的請求。
      比如,我要對一個接口進行壓力測試  http://10.0.5.52:17070/tbs/ip/search?ip=218.17.158.4&async=1 ,其中 ip= 后的值是可變參數,那么我可以把 post.lua 腳本改寫成這樣,

       

      wrk.method = "GET"
      wrk.body = ""
      wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

      request = function()
      ip = tostring(math.random(1, 255)).."."..tostring(math.random(1, 255)).."."..tostring(math.random(1, 255)).."."..tostring(math.random(1, 255))
      path = "/tbs/ip/search?async=1&ip=" .. ip
      return wrk.format(nil, path)
      end
      這一段描述了非常簡單的一個 function, 把 ip 這個變量,用4個 1到255之間的隨機數拼成字符串后,作為接口 path 的一部分,發送 GET 請求
      tostring 是把 int 轉換為 string,.. 可以理解為在 java 中對字符串使用 “+” 的操作來連接。
      另存為 test.lua ,並且把這個腳本放在與 wrk 可執行文件平級的位置。

    4. 執行測試。

      xieludeMacBook-Pro:wrk xielu$ ./wrk -t200 -c2000 -d60s -s post.lua --latency http://10.0.5.52:17070
      Running 1m test @ http://10.0.5.52:17070
      200 threads and 2000 connections
      Thread Stats Avg Stdev Max +/- Stdev
      Latency 807.86ms 134.63ms 1.97s 75.92%
      Req/Sec 6.95 6.22 70.00 87.60%
      Latency Distribution
      50% 794.69ms
      75% 885.46ms
      90% 955.05ms
      99% 1.15s 
      18208 requests in 1.00m, 6.26MB read
      Socket errors: connect 0, read 0, write 0, timeout 1129
      Requests/sec: 302.94
      Transfer/sec: 106.74KB


      可以看到,在 60s 內 發送了18208 個請求,接口的響應已經非常慢了,達到1s。

      如果需要同時監控被測服務的負載,可以打開 zabbix 進行監控,獲取到的數據更多

    5. 踩過的坑:
      test.lua 文件必須與 wrk 的可執行文件在同一層目錄下,否則會報錯找不到腳本,然后執行請求只會得到很多 404 的響應……
      wrk 受操作系統的限制,open file 默認為 1024(linux),256(MACOS),所以大家在操作的時候把這個值設大一些。

      xieludeMacBook-Pro:wrk xielu$ ulimit -a

      core file size          (blocks, -c) 0

      data seg size           (kbytes, -d) unlimited

      file size               (blocks, -f) unlimited

      max locked memory       (kbytes, -l) unlimited

      max memory size         (kbytes, -m) unlimited

      open files                      (-n) 4096

      pipe size            (512 bytes, -p) 1

      stack size              (kbytes, -s) 8192

      cpu time               (seconds, -t) unlimited

      max user processes              (-u) 709

      virtual memory          (kbytes, -v) unlimited


      可以看到,我本機上的已經修改為 4096。
      如何修改? 使用 root 用戶,執行 ulimit -n 你想要的數字。

    6. 延伸閱讀:
      wrk 的工作原理,以及如何執行腳本? http://www.tuicool.com/articles/IFjIJjU
      lua 怎么寫?http://www.runoob.com/lua/lua-tutorial.html
      復雜測試場景參考 http://www.cnblogs.com/rainy-shurun/p/5867946.html
    7. wrk中的pipe line怎么做
      首先,wrk 支持 luaJIT,所以使用wrk 壓測過程中要實現pipe line的話,是在scrip腳本中定義的。
      先來了解下 wrk 各個階段的方法,可以通過自定義同名方法來實現自己想要的功能:

      初始化:

      function setup(thread)

      在腳本文件中實現setup方法,wrk就會在測試線程已經初始化但還沒有啟動的時候調用該方法。wrk會為每一個測試線程調用一次setup方法,並傳入代表測試線程的對象thread作為參數。setup方法中可操作該thread對象,獲取信息、存儲信息、甚至關閉該線程。
      這個方法使用的頻率較少。

      運行時:
      function init(args)
      注意!!pipe line 在這里定義了!!!!!
      先說明,pipe line 中的每個action, 舉個栗子,順序發送請求的話,需要定義一個table, 在table中根據index的順序定義request.
      這個方法的意思是
      定義兩個全局變量 request,respones並初始化為0
      使用wrk 初始化每個請求並作為table的一個元素
      最后把這些請求連接起來,即可

      --request 初始化
      function init(args)
      requests = 0
      responses = 0
      local p = {}
      headers = {["Content-Type"] = "application/json",["accessToken"] = "1"}
      p[1] = wrk.format("POST", "/1",headers,"test=1")
      p[2] = wrk.format("POST", "/2",headers,"test=2")
      p[3] = wrk.format("POST", "/3",headers,"{\"test\":\"3\",\"pageNo\":1,\"pageSize\":2")
      p[4] = wrk.format("POST", "/4",headers,"{\"test\":\"4\",\"pageNo\":1,\"pageSize\":20")
      req = table.concat(p)
      end
      --接收到請求后如何處理
      function response(status, headers, body)
      responses = responses + 1
      if status ~= 200 then
      wrk.thread:stop()
      end
      end
       
      --開始請求
      function request()
      requests = requests + 1
      return req
      end
       
      --delay,這個暫時沒用到,放在這里占位子
      function delay()
      end
       
      通過對luaJIT的支持,wrk可以實現強大多變的測試場景,而且對於延遲數據的統計也較為准確(參照物是jmeter)
       
      關於lua腳本的擴展,歡迎參考
       
      補充:lua對於轉義符 \ 預先做了一層轉移,所以如果使用 \轉義的話,需要改為\\\


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM