負載壓力測試工具 - JMeter

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 看不到效果

 

更多的測試報告,可以參考

https://jmeter.apache.org/usermanual/listeners.html

 

執行測試

很顯然綠色的箭頭就是開始執行測試,但是我習慣開始執行測試之前,先清除所有的 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,這個腳本主要做兩件事

  1. 每次測試之前先清掉上一次的測試結果
  2. 執行 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

Image result for microsoft+mvp+logo