使用 WRK 压力测试工具对 ASP.NET Core 的接口进行压力测试
0. 簡要介紹
WRK 是一款輕量且易用的 HTTP 壓力測試工具,通過該工具我們可以方便地對我們所開發的 WebAPI 項目進行壓力測試,并且針對測試的情況返回結果。
PS:Wrk 并不能針對測試的結果生成動態的圖表,如果有這種需要,可以嘗試使用另一款工具 Vegeta。該項目使用的 Golang 進行編寫,其 GitHub 地址為:https://github.com/tsenart/vegeta
下面的內容就是一個標準的測試結果信息:
Copy
針對 127.0.0.1:8080 進行壓力測試wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.htmlCopy
這里是測試結果Running 30s test @ http://127.0.0.1:8080/index.html ?12 threads and 400 connections ?Thread Stats ? Avg ? ? ?Stdev ? ? Max ? +/- Stdev ? ?Latency ? 635.91us ? ?0.89ms ?12.92ms ? 93.69% ? ?Req/Sec ? ?56.20k ? ? 8.07k ? 62.00k ? ?86.54% ?22464657 requests in 30.00s, 17.76GB read Requests/sec: 748868.53 Transfer/sec: ? ?606.33MB1. 安裝
關于 OS X 與 Windows 的安裝可以參考 Wrk 官方 WIKI 進行操作,本文主要講解一下 CentOS 7.x 下如果進行編譯。
Copy
sudo yum groupinstall 'Development Tools' sudo yum install -y openssl-devel git git clone https://github.com/wg/wrk.git wrk cd wrk make編譯之后,你會得到如下結果:
可以看到生成了一個 wrk 的可執行文件,你可以將其添加到環境變量的 PATH 當中,這里就不再贅述,我們等會兒使用的時候直接 ./wrk 使用。
2. 命令說明
Copy
./wrk -H "Authorization: Bearer TokenValue" -t 2 -c 50 -d 10s --latency --timeout 1s "http://"上面的命令就是一個典型的壓力測試命令,關于參數的含義請看下表。
| -c | 與 HTTP 保持連接的連接數,最終每個線程能夠處理的為 連接數/線程數。 | -c 50 |
| -d | 指定壓力測試的時間有多長。 | -d 10s,其他單位有 2s,2m,2h 如果不帶單位的話,默認為秒。 |
| -t | 壓力測試時所使用的線程數目,最好為你 CPU 核心的數量。 | -t 4 |
| -s | 指定要執行的 Lua 腳本 | -s ./post.lua |
| -H | 執行請求的時候所附帶的 Header 組。 | -H "User-Agent: wrk" |
| --latency | 打印詳細的統計信息。 | --latency |
| --timeout | 每次請求所返回響應體的時間,如果超過了配置的時間,則視為請求超時。 | --timeout 1s |
3. 開始壓力測試
執行了上述代碼之后我們可以看到很直觀的信息,第一個就是 20s 的時間內完成了 2887 次請求,一共接受到了 2.46MB 的數據。在 Socket errors 里面我們可以看到有 35 個請求產生了超時的情況,每秒執行的請求大概為 144.20 個,每秒的數據傳輸大概為 125.75 KB。
除此之外,還說明了平均每次請求所消耗的時間為 338.44 ms,最極端的情況為 994.27ms。
4. LUA 腳本
在第三節我們可以看到一些標準的 GET 請求我們可以直接通過指定命令來進行測試,即便該接口有授權驗證,我們可以通過?-H?參數來指定?Authorization?頭來實現權限驗證。
但是針對一些復雜的情況,我們就需要編寫 LUA 腳本來實現壓力測試了。
官方編寫了很多的 LUA 腳本 DEMO ,存放在 GitHub 上面,其地址為:https://github.com/wg/wrk/tree/master/scripts。
這里我們以實現 POST 請求為例:
Copy
wrk.method = "POST"wrk.body ? = '{"username":"admin","password":"123qwe","rememberClient":true}'wrk.headers["Content-Type"] = "application/json"這里我們的接口地址更改了一下,改變成了 Login 接口,該接口需要傳入用戶名與密碼,并且其 Method 為 POST。
將上述 LUA 腳本保存為 post.lua 文件,然后通過?-s?參數指定 LUA 腳本的路徑并執行。
5. LUA 腳本相關詳解
WRK 中執行 HTTP 請求的時候,調用 Lua 分為 3 個階段,setup、running、done,每個 WRK 線程中都有獨立的腳本環境。
5.1 WRK 的全局屬性
Copy
wrk = { ?scheme ?= "http", ?host ? ?= "localhost", ?port ? ?= nil, ?method ?= "GET", ?path ? ?= "/", ?headers = {}, ?body ? ?= nil, ?thread ?= <userdata>, }5.2 WRK 的全局方法
Copy
-- 生成整個request的string,例如:返回-- GET / HTTP/1.1-- Host: tool.lufunction wrk.format(method, path, headers, body)-- 獲取域名的IP和端口,返回table,例如:返回 `{127.0.0.1:80}`function wrk.lookup(host, service)-- 判斷addr是否能連接,例如:`127.0.0.1:80`,返回 true 或 falsefunction wrk.connect(addr)5.3 Setup 階段
setup()?方法是在線程創建之后,啟動之前。
Copy
function setup(thread)-- thread提供了1個屬性,3個方法-- thread.addr 設置請求需要打到的ip-- thread:get(name) 獲取線程全局變量-- thread:set(name, value) 設置線程全局變量-- thread:stop() 終止線程5.4 Running 階段
Copy
function init(args)-- 每個線程僅調用1次,args 用于獲取命令行中傳入的參數, 例如 --env=prefunction delay()-- 每個線程調用多次,發送下一個請求之前的延遲, 單位為msfunction request()-- 每個線程調用多次,返回http請求function response(status, headers, body)-- 每個線程調用多次,返回http響應5.5 Done 階段
可以用于自定義結果報表,整個過程中只執行一次。
Copy
function done(summary, latency, requests)latency.min ? ? ? ? ? ? ?-- minimum value seenlatency.max ? ? ? ? ? ? ?-- maximum value seenlatency.mean ? ? ? ? ? ? -- average value seenlatency.stdev ? ? ? ? ? ?-- standard deviationlatency:percentile(99.0) -- 99th percentile valuelatency(i) ? ? ? ? ? ? ? -- raw value and countsummary = { ?duration = N, ?-- run duration in microseconds ?requests = N, ?-- total completed requests ?bytes ? ?= N, ?-- total bytes received ?errors ? = { ? ?connect = N, -- total socket connection errors ? ?read ? ?= N, -- total socket read errors ? ?write ? = N, -- total socket write errors ? ?status ?= N, -- total HTTP status codes > 399 ? ?timeout = N ?-- total request timeouts ?} }而官方的?setup.lua?腳本則是重載這些方法并使用的一個 DEMO:
Copy
-- example script that demonstrates use of setup() to pass-- data to and from the threadslocal counter = 1local threads = {}function setup(thread) ? thread:set("id", counter) ? table.insert(threads, thread) ? counter = counter + 1endfunction init(args) ? requests ?= 0 ? responses = 0 ? local msg = "thread %d created" ? print(msg:format(id))endfunction request() ? requests = requests + 1 ? return wrk.request()endfunction response(status, headers, body) ? responses = responses + 1endfunction done(summary, latency, requests) ? for index, thread in ipairs(threads) do ? ? ?local id ? ? ? ?= thread:get("id") ? ? ?local requests ?= thread:get("requests") ? ? ?local responses = thread:get("responses") ? ? ?local msg = "thread %d made %d requests and got %d responses" ? ? ?print(msg:format(id, requests, responses)) ? endend6. 參考資料
wrk中的lua腳本:https://type.so/linux/lua-script-in-wrk.html
http 性能測試 wrk使用教程:https://juejin.im/post/5a59e74f5188257353008fea
原文地址:https://www.cnblogs.com/myzony/p/9798116.html
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結
以上是生活随笔為你收集整理的使用 WRK 压力测试工具对 ASP.NET Core 的接口进行压力测试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微服务之:从零搭建ocelot网关和co
- 下一篇: asp.net ajax控件工具集 Au