JMeter 是我目前正在使用的壓力測試工具,支援 GUI、CLI,配置容易,也能自動化,網路上的教學資源也相當的豐富,在這裡我將分享我常用的配置,希望對你有幫助

開發環境
- Windows 11
- Rider 2022.2.3
安裝
安裝 JMeter
在 powershell | batch 使用 scoop 安裝
scoop install jmeter
安裝完成後,在 powershell | batch 輸入 jmeter,便可以看到

安裝 JMeter Plugin Manager
下載 jmeter-plugins-manager-1.7.jar,https://jmeter-plugins.org/install/Install/ 並放到 JMeter 資料夾裡的 lib/ext下,然後重啟 JMeter,因為我是用 scoop 安裝的,所以 jmeter lib/ext 的路徑為
%UserProfile%\scoop\apps\jmeter\current\lib\ext
重啟 jmeter 之後, JMeter Plugin Manager 已經安裝好了

常用 Plugin
以下是我常用的 Plugin,這些都可以在 JMeter Plugin Manager 安裝
- Custom Thread Groups
- Extended CSV dataset config (可以用來讀取外部參數檔)
用 JMeter GUI 快速建立一個測試
每一個測試目標所需要準備的前置作業都不一樣,我這裡用一個最快的設定配置
新增一個 Thread Group → 控制 TPS → Sampler (採樣器) → Assertion → Listeners (收集測試結果)
Thread Group (Ultimate Thread Group)
Thread Group 主要是配置,同時用多少個 Thread (User) 送出 Request 的數量。
注意,這裡並不是 TPS / RPS 的控制數
這裡我選用的是 Ultimate Thread Group,配置如下:
Action to be token after a Sample error (採樣器錯誤發生後要執行的動作)
- Continue :會繼續向下執行後面的動作,直到所有的動作執行完成。
- Start Next Thread Loop:停止目前的 Thread Group,進入下一個 Thread Group。
- Stop Thread:停止目前的 Thread Group。
- Stop Test:等待目前的 Thread Group 結束後,停止測試。
- Stop Test Now:立即中止測試。
Thread Schedule
- Start Threads Count:執行緒數量
- Initial Delay,sec:開始執行緒之前的延遲,幾秒後才開始啟動執行緒。
- Startup Time ,sec:執行緒的加速方式,幾秒後全部啟動。
- Hold Load For,sec:執行緒啟動後執行的時間。
- Shutdown Time:執行緒關閉的速度,幾秒後全部停止。
設定結果如下圖:

控制 TPS (Precise Throughput Timer)
Precise Throughput Timer 可以很精準的控制吞吐量,就算 Thread Group 設定很大量 Thread (User) 它都會想辦法限制,這算是誤差值很低的 Throughput Timer,配置如下:
- Target throughput:期望的 TPS。
- Throughput period,sec:多少秒達到 TPS。
- Test duration,sec:持續測試時間,這裡和 Thread Group 一致。
- Number of threads in the batch:準備多少個執行緒後,一起送出請求。
設定結果如下圖:

Sampler (Http Request)
把測試目標的位置、參數放上去,這跟 Postman 沒啥兩樣,就不多著墨了

另外,更多的 http request 配置都在 Config Element

更多的採樣器(Sample)可以參考
https://jmeter.apache.org/usermanual/component_reference.html#samplers
Listeners (收集測試結果)
加入 View Results Tree 和 Summary Report

View Results Tree
這裡就是每一個 Request 所執行的結果,但我需要的是整個統計,不需要紀錄每一個細節,當我確定配置沒有問題後,我會把 Errors 勾起來,只記錄 Error,印象中只要得到 Http Status ≥ 400 就會得到錯誤
Write results to file (選用) :報告輸出位置
這裡我為了讓測試報告的路徑集中在 *.jmx 底下,我使用了 __BeanShel + org.apache.commons.io.FilenameUtils + org.apache.jmeter.services.FileServer,組合出我想要的路徑,在 User Defined Variables 新增兩個變數
currentFolder
${__BeanShell(import org.apache.jmeter.services.FileServer; FileServer.getFileServer().getBaseDir())}
currentTestPlanFileName
${__BeanShell(import org.apache.jmeter.services.FileServer;import org.apache.commons.io.FilenameUtils;
FilenameUtils.getBaseName(FileServer.getFileServer().getScriptName()))}
設定如下圖:

Request 的結果如下圖:

輸出檔案設定如下圖:

Summary Report
統計報告,可惜的是這裡沒有 P90、P95、P99 的資訊

Generate Summary Results
預設在 cli 模式就會使用,這個測試結果就會把 P90、P95、P99 的資訊寫在 statistics.json,在 GUI 看不到效果

更多的測試報告,可以參考
執行測試
很顯然綠色的箭頭就是開始執行測試,但是我習慣開始執行測試之前,先清除所有的 log

除錯
所有的執行 log 都會被記錄在這裡

Debug Sampler 列出相關的參數,也是快速觀測變數的手段之一

執行結果如下圖:

JMeter CLI
GUI 並不適合用來跑負載測試,僅用來建立測試計畫,確定都沒有問題之後再透過 CLI 執行測試,CLI 參數如下:
- -n: 讓 JMeter 於非圖形介面模式(non-gui mode)執行
- -t: 執行計畫(plan)名稱,副檔名為JMX
- -l: 執行結果(result)儲存名稱,副檔名為JTL
- -j: 執行紀錄(log)儲存名稱
- -r: 執行遠端測試 (依據 JMeter prorerty "remote_hosts" 設定)
- -R: 執行遠端測試 (特定主機,需要於命令給予伺服器清單)
- -g: 產生報表儀表板,CSV檔案(儲存路徑)
- -e: 負載測試後產生報表儀表板
- -o: 輸出資料夾名稱,輸出資料為負載測試後產生報表儀表板 (這個資料夾不存在或內容必須為空)
Example
在 CLI 模式下啟動 JMeter 並將結果轉成 HTML Report:
jmeter -n -t first.jmx -l result.jtl -e -o report
更多的 CLI 配置請參考
https://jmeter.apache.org/usermanual/get-started.html#running
為了讓每一次執行 jmeter cli 都能夠順利,且讓腳本能跨平台我採用 taskfile shell + nushell,這個腳本主要做兩件事
- 每次測試之前先清掉上一次的測試結果
- 執行 jmeter 測試
# Taskfile.yml
version: "3"
dotenv: [ "secrets/secrets.env" ]
tasks:
clear-log:
cmds:
- nu -c 'rm -rf ./jmeter.log'
- nu -c 'rm -rf ./temp'
first:
desc: first sample
cmds:
- task: clear-log
- nu -c 'rm -rf ./first'
- jmeter -n -t first.jmx -l ./first/result.jtl -e -o ./first
執行結果如下

完成測試後,在 first 資料夾可以得到以下檔案

index.html
視覺化的報告

statistics
這裡就有 TPS、P90(ms)、P95(ms)、P99(ms) 的數據,我主要是用這一份報告來得知目前服務的資源配置,能消化多少 TPS、響應時間有多快 P90、P95、P99

其他案例使用
讓不同的 Thread 使用不同的數字不會碰撞
當被測目標的唯一值/隔離因子是號碼,這時候就需要一組連續的號碼,每一個執行緒取用的號碼都不一樣,這樣才可以讓多個執行緒並行送出請求而不會發生錯誤/碰撞 HttpStatus Code (409)
Config Element / Counter 則是滿足了這個場景,配置非常的簡單就不再著墨了,如下圖:

- Starting value:初始值,long 整型,預設 0。
- Increment:每次迭代的遞增值,預設 0,表示不增加。
- Maximum value:最大值,包含此值。
- Number format:數字呈現方式,預設不格式化。
- Exported Variable Name:變數名稱。
- Track counter independently for each user:每個使用者(Thread)都有一個獨立的計數器。
- Reset counter on each Thread Group Iteration:每次 Thread Group 迭代時計數器將重置為初始值。預設,計數器是對所有 Thread 共享的

讓不同的 Thread 使用不同的 UUID 不會碰撞
被測目標若是使用 GUID 當成是唯一值/隔離因子,則使用 ${__UUID()}
範例位置
sample.dotblog/Test/Lab jmeter sample at master · yaochangyu/sample.dotblog (github.com)
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET