壓測工具wrk和Artillery的比較

這兩天抽空使用了一下兩款壓測工具node

  • wrk
  • Artillery

而且經過兩款工具對產品的兩個環境進行了測試ios

工具比較

wrk

wrk自身性能就很是驚人,使用epoll這種多路複用技術,因此能夠用少許的線程來跟被測服務建立大量鏈接,進行壓測,同時不佔用過多的CPU和內存。git

命令很是簡單github

wrk -t8 -c200 -d30s --latency  "http://www.baidu.com"

這樣就能夠進行最簡單的壓測。可是真實使用起來確定會有複雜的場景,好比先要登陸取到token再進行下一步。好在wrk支持lua腳本,提供了幾個階段的hook來讓用戶自定義邏輯,具體能夠看github上的官方提供的script sample。docker

我這裏舉一個獲取token的例子json

-- @Author: wangding
-- @Date:   2017-12-06 15:13:19
-- @Last Modified by:   wangding
-- @Last Modified time: 2017-12-06 23:57:49
local cjson = require "cjson"
local cjson2 = cjson.new()
local cjson_safe = require "cjson.safe"

token = nil
path  = "/api/auth/login"
method = "POST"

wrk.headers["Content-Type"] = "application/json"

request = function()
   return wrk.format(method, path, nil, '{"username":"demo@demo.com","password":"demo"}')
end

response = function(status, headers, body)
   if not token and status == 200 then
      value = cjson.decode(body)
      token = value["token"]
      method = "GET"
      path  = "/api/contact?size=20&page=0"
      wrk.headers["Authorization"] = token
   end
end

requestresponse 分別是兩個hook,每次請求都會調用,那麼這裏request的邏輯就是一開始就使用POST請求/api/auth/login而且帶有body,請求完成進入response,第一次token確定是nil,因此把repose的token解析出來付給全局變量token,以後改寫全局變量爲GET請求地址/api/contact而且設置了header包含Authorizationapi

這樣實際是變通的實現了一個簡單scenario的測試,那麼問題來了,若是場景更復雜怎麼辦?寫確定是能夠寫的,可是並不直觀,因此wrk不太適合一個包含有序場景的壓力測試。tomcat

再來看一下wrk的report,這一點是我最喜歡的bash

wrk -t8 -c200 -d30s -H "Authorization: token" --latency "http://10.0.20.2:8080/api/contact?size=20&page=0"
Running 30s test @ http://10.0.20.2:8080/api/contact?size=20&page=0
  8 threads and 200 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   769.49ms  324.43ms   1.99s    72.08%
    Req/Sec    33.37     21.58   131.00     62.31%
  Latency Distribution
     50%  728.97ms
     75%  958.69ms
     90%    1.21s
     99%    1.74s
  7606 requests in 30.03s, 176.69MB read
  Socket errors: connect 0, read 0, write 0, timeout 38
Requests/sec:    253.31
Transfer/sec:      5.88MB

開啓8線程,每一個線程200個鏈接,持續30s的調用,能夠看到報告中直接給出了最關鍵的指標QPS,這裏的值是253.31。平均響應時間是33.37ms。簡單直接,很是易懂。併發

可是這裏面有個坑就是cjson這個lua module的使用,不可使用lua5.2,必須使用lua5.1並且須要特定的wrk和cjson。我直接使用docker來封裝這個運行環境,壞處是docker使用host模式自己性能可能就有影響。

Artillery

一開始看到Artillery主要是由於它支持帶場景的測試,也就是帶有步驟,看一眼獲取token再進行下一步的腳本。

config:
  target: "http://10.0.20.2:8080"
  phases:
    - duration: 30
      arrivalRate: 100
scenarios:
  - flow:
    - post:
        url: "/api/auth/login"
        json:
          username: "demo@demo.com"
          password: "demo"
        capture:
          json: "$.token"
          as: "token"
    - log: "Login token: {{ token }}"
    - get:
        url: "/api/contact?size=20&page=0"
        headers:
          Authorization: "{{ token }}"

flow就是表示步驟,duration表示持續30s,跟wrk不一樣的是沒有thread的概念,Artillery是nodejs寫的,arrivalRate表示每秒模擬100個請求,因此兩個參數乘起來就是3000個請求。看一下報告什麼樣:

All virtual users finished
Summary report @ 12:45:41(+0800) 2017-12-08
  Scenarios launched:  3000
  Scenarios completed: 3000
  Requests completed:  3000
  RPS sent: 98.33
  Request latency:
    min: 15.7
    max: 179.1
    median: 19
    p95: 25.8
    p99: 37.5
  Scenario duration:
    min: 16.4
    max: 191.4
    median: 19.8
    p95: 27
    p99: 44.6
  Scenario counts:
    0: 3000 (100%)
  Codes:
    200: 3000

這裏的RPS sent是指前10s平均發送請求數,因此這個和咱們常說的QPS仍是不同的。若是想提升request的總數就要增長arrivalRate,好比上文wrk一共發了7606請求,那麼這裏arrivalRate提升到200一共能夠在30s發6000次,可是改完就悲劇了,

Warning: High CPU usage warning.
See https://artillery.io/docs/faq/#high-cpu-warnings for details.

Artillery一直在不斷的告警,說明這個工具自身的侷限性致使想要併發發送大量請求的時候,本身就很佔CPU。

小結

wrk小巧並且性能很是好,報告直觀。可是對於帶多個步驟的壓測場景無力。
Artillery太耗資源,並且報告不直觀。不建議採用
除此以外惟一帶場景的測試工具就是Jmeter了,可是Jmeter自己使用JVM是否能夠短期模擬大量併發,仍是須要測試,建議與wrk作對比實驗。

附錄:簡單的性能調優

在用wrk測試GET請求的時候,發現不管如何提升鏈接數,QPS都是在250左右,此時CPU和內存都沒有佔滿。懷疑是有其餘瓶頸。最後發現Spring Boot內嵌的tomcat線程沒法突破200,因此看了一下文檔,發現默認最大線程數就是200,對application.yml進行了調整(同時調整了多個服務,包括gateway)

server:
  tomcat:
    max-threads: 1000
    max-connections: 2000

調整以後開啓8線程,每一個100個鏈接測試

Running 30s test @ http://10.0.10.4:8769/api/contact?size=20&page=0
  8 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   235.56ms  267.57ms   1.98s    91.07%
    Req/Sec    72.12     30.19   190.00     68.17%
  Latency Distribution
     50%  166.46ms
     75%  281.10ms
     90%  472.03ms
     99%    1.45s
  15714 requests in 30.03s, 4.77MB read
Requests/sec:    523.29
Transfer/sec:    162.56KB

能夠看到QPS達到了500以上直接翻倍了,再嘗試提升鏈接數發現瓶頸就在內存了。

此外以前用公網作了一次壓測,QPS只有10左右,看了一下阿里雲的監控原來是出口帶寬形成的,只有1MB的出口帶寬,鏈接數調多大也沒用。

將來還須要進行場景的細化,再決定是否使用不一樣的工具進行測試。

相關文章
相關標籤/搜索