Apache JMeter 使用教學手冊

版本:v1.0(已完成第 1–16 章與附錄 A–E;持續維護優化)
適用對象:完全未接觸過效能測試 / JMeter 的新進開發與測試人員
文件目標:協助 1~2 天內快速具備撰寫並執行基本壓力測試腳本的能力,並建立後續進階自學基礎。


快速導讀

若你是第一次接觸 JMeter,建議依序閱讀:

  1. Part 1(必讀):了解 JMeter 是什麼、安裝、基礎 GUI 操作。
  2. Part 2:學會設計一個可維護的測試計畫(參數化、控制器、Assertion)。
  3. Part 3:掌握報表分析與常見最佳實務(非 GUI、分散式、效能瓶頸初步診斷)。
  4. Part 4:實戰情境(API / Web / DB / 企業案例)。
  5. Part 5:若需考 JMeter 認證或建置團隊基準能力。
  6. 附錄:錯誤排除、報告範本、學習資源、Checklist。

目錄(Table of Contents)

Part 1. 基礎入門(Ch.1–3)

Part 2. 測試計畫設計(Ch.4–7)

Part 3. 進階應用(Ch.8–10)

Part 4. 專案實戰(Ch.11–13)

Part 5. 認證與進階知識(Ch.14–16)

Part 6. 附錄(Appendices)


1. JMeter 簡介

1.1 JMeter 的定位與用途

Apache JMeter 是一款開源(Java 編寫)的負載與效能測試工具,最初設計用於 Web(HTTP) 測試,如今已支援多種協定:HTTP(S)、JDBC、JMS、FTP、TCP、SOAP、gRPC(透過外掛)、MQTT 等。其核心使命:模擬多使用者併發,量測系統在壓力下的反應時間、吞吐量、錯誤率,協助定位瓶頸。

典型使用場景:

  • 測試 API 在 100 / 500 / 1000 併發下之平均延遲 (Avg / P95 / P99)
  • 驗證新版本部署後的效能回歸
  • 預估硬體或雲端資源擴充需求(容量規劃)
  • 模擬高峰(行銷活動、批次入帳、補貨作業)

1.2 常見測試類型

類型目的範例觀察指標
負載測試 (Load)正常或預期峰值行為0→200 虛擬用戶Avg、Throughput、Error%
壓力測試 (Stress)找出系統崩潰點持續升壓至錯誤率飆升臨界併發、錯誤率、資源耗盡
容量測試 (Capacity)確定支援多少用戶線性提升穩定最大併發
耐久/穩定性 (Soak)長時間資源洩漏8~24h 低~中壓記憶體、GC、錯誤率趨勢
基準測試 (Benchmark)比較版本或方案A/B API 實作同負載指標差異

1.3 與其他工具比較

工具語言優點適用場景侷限
JMeterJava(GUI+非 GUI)社群大、外掛多、GUI 低門檻團隊快速導入、多協定GUI 高負載時耗資源
GatlingScala高效、可程式化 DSL需程式化與 CI 整合學習曲線偏高
k6Go(JavaScript 腳本)易寫、Cloud 服務API / 微服務雲端某些協定需擴充
LocustPythonPython 生態自訂行為、流量模型高併發需調整
LoadRunner專有功能完整大型企業、複雜協定授權成本高

選擇建議:若需快速導入 + 多人圖形化協作 + 可擴充 → 先選 JMeter。後續若腳本維護變複雜或需高度程式化,再評估 Gatling / k6。

1.4 概念流程圖

flowchart LR A[需求/測試目標] --> B[場景設計] B --> C[建置 JMeter Test Plan] C --> D[參數化 / 控制器 / 驗證] D --> E[本機驗證 (GUI)] E --> F[非 GUI / 分散式執行] F --> G[結果彙整 / HTML 報表] G --> H[分析瓶頸 / 產出結論] H --> I[調校 / 回饋開發 / 再測]

1.5 本章實務案例

需求:行銷活動預期 500 同時使用者查詢商品 API,需確認 API P95 < 800ms。 行動:建立 JMeter 測試計畫 → Thread Group 設定 500 使用者,Ramp-up 300 秒,持續 5 分鐘 → 檢視 Summary / Aggregate Report。 輸出:若 P95 超標,記錄指標並回報後端做索引或快取優化。

1.6 注意事項(初學者常犯)

  • 直接用 GUI 模式跑 1000+ threads 導致本機資源飽和 → 應改非 GUI / 分散式
  • 沒加 Assertion 導致錯誤頁面也被當成功 → 一律加 Response Code 或字串驗證
  • 無計畫地升壓(一次丟極大併發)→ 無法定位臨界點,改用階梯式(階段性提升)

2. 安裝與環境設定

2.1 系統需求

  • Java:JDK 8+(建議 11 或 17 LTS)
  • 記憶體:建議 8GB 以上(壓測機依併發放大)
  • OS:Windows / Linux / macOS 均可

2.2 下載來源

2.3 安裝流程

Windows:

  1. 安裝 JDK(確認 java -version
  2. 下載 Apache JMeter 二進位壓縮檔
  3. 解壓至例如:C:\tools\apache-jmeter-5.6.3
  4. 執行 bin\jmeter.bat

Linux / macOS:

tar -xzf apache-jmeter-*.tgz
export JMETER_HOME=~/apache-jmeter-5.6.3
export PATH="$JMETER_HOME/bin:$PATH"
jmeter &

2.4 目錄結構

目錄說明
/bin啟動腳本、非 GUI 執行指令 (jmeter, jmeter-server)
/lib核心與第三方套件 JAR
/lib/ext放外掛(JMeter Plugins)
/extras轉換工具、範例(如 ant 任務)
/docs官方文件

2.5 常見安裝問題

問題原因解法
無法啟動 GUI:記憶體錯誤預設 Heap 太小編輯 bin/jmeter.bat / jmeter 調整 -Xms1g -Xmx4g
中文顯示亂碼字型或編碼啟動加參數 -Dfile.encoding=UTF-8
無法執行 HTTPS 測試憑證問題匯入 JMeter 產生的 CA 憑證(代理錄製時)
JDK 版本不符JAVA_HOME 錯誤重新設定環境變數

2.6 調整啟動參數

編輯 bin/jmeter.propertiesuser.properties

# 增加結果緩衝 (大量取樣時降低 IO)
mode=batch
# 禁用不必要的 GUI 元件提升穩定性
jmeter.reportgenerator.overall_granularity=60000

建議:自訂屬性盡量放 user.properties,方便版本控制。

2.7 本章實務練習

  1. 完成安裝後,執行 jmeter -v 確認版本。
  2. 調整記憶體參數:設定 HEAP=-Xms1024m -Xmx4096m
  3. 建立一個 user.properties 並加入:sample_variables=SESSION_ID

2.8 注意事項

  • 測試機與被測系統(SUT)應分離 → 避免 CPU / I/O 競爭影響評估
  • 控制版本:將 *.jmxuser.propertiesCSV啟動腳本 納入 Git
  • 測試數據與環境隔離:避免對生產資料造成污染

3. JMeter 使用者介面 (GUI)

3.1 元件總覽

類別代表元件作用
Test PlanTest Plan測試計畫根節點、變數與前置設定
Thread GroupThread Group / Stepping / Ultimate模擬使用者併發與執行節奏
SamplerHTTP Request / JDBC Request / Debug Sampler送出實際請求
ConfigCSV Data Set / HTTP Header / User Defined參數化與預設設定
Logic ControllerIf / Loop / Transaction / Throughput控制流程與群組化
TimerConstant / Uniform Random / Think Time插入等待模擬真人行為
Pre/Post ProcessorRegular Expression Extractor / JSR223請求前後處理、抽取、動態資料
AssertionResponse / Duration / Size驗證回應正確性
ListenerView Results Tree / Summary / Aggregate / HTML收集與顯示結果

3.2 建立第一個測試計畫(Hello HTTP)

步驟:

  1. 開啟 JMeter,右鍵 Test Plan → Add → Threads → Thread Group
  2. Thread Group 設定:Threads=5、Ramp-up=5、Loop=2
  3. 右鍵 Thread Group → Add → Sampler → HTTP Request
    • Server Name: postman-echo.com
    • Method: GET
    • Path: /get
    • (可加參數) Add → Parameter: foo=bar
  4. 加入 Listener:右鍵 Thread Group → Add → Listener → View Results Tree、Summary Report
  5. 按「綠色 Start」執行
  6. 在 View Results Tree 檢視 Request / Response;大量壓測時移除該 Listener,改只保留 Summary Report。

3.3 儲存與版本控管

  • 檔案 → Save Test Plan As → api_basic.jmx
  • 建議:一個主計畫 + 多個模組化 Include Controller(後續 Part 2 說明)
  • 以 Git 管理:提交時附測試說明 README(含測試目標、指標、版本)

3.4 GUI 效能使用守則

守則原因
減少不必要的 Listener(尤其是 View Results Tree)占用大量記憶體與 I/O
大規模壓測改用非 GUI (jmeter -n)GUI 只是設計工具,不適合生產壓力
使用 CSV 而非巨量插件輸出降低即時刷新成本
啟動前清除舊結果避免誤判與累積資料

3.5 Mermaid:基本測試計畫組成

graph TD TP[Test Plan] --> TG[Thread Group] TG -->|執行順序| S1[HTTP Sampler] TG --> S2[JDBC Sampler] S1 --> A1[Assertion] S1 --> L1[Listener] S2 --> L1 TG --> C1[Config: CSV Data] TG --> T1[Timer]

3.6 本章實務練習

建立 postman-echo 測試:

  1. Threads=10,Ramp-up=10,Loop=3
  2. 新增 Uniform Random Timer:延遲 500ms ±300ms
  3. 新增 Response Assertion:包含字串 "args"
  4. 執行後觀察錯誤率=0 並記錄 Avg、Min、Max。

3.7 常見初階錯誤

  • 把 Ramp-up=0:所有 threads 同時啟動 → 導致服務突刺
  • 忘記加 Timer:與實際使用者行為不符
  • 不加 Assertion:錯誤回應被忽略

3.8 小結

你現在應能:

  • 安裝並啟動 JMeter
  • 認識主要元件類別
  • 建立並執行簡單 HTTP 測試 接下來 Part 2 將深化:參數化、控制流程、可維護架構與驗證策略。

(後續章節將於下一階段回覆補上)


4. 測試計畫基礎

4.1 目標與原則

設計一個可維護、可重複、可擴充的測試計畫,重點:

  • 可讀性:命名清楚、層次分明
  • 可參數化:資料與腳本分離
  • 可重複:環境差異靠變數 / properties 切換
  • 可驗證:Assertion 一致、指標明確
  • 可擴充:模組化(登入、下單、查詢)可被重用

4.2 命名規範建議

類型命名格式範例說明
Test Plan 檔名<domain>-<scenario>-v<版號>.jmxecommerce-search-v1.jmx區分領域與場景
Thread Group[TG]<用途>-<併發>-<階段>[TG]SearchUsers-200-Steady指明角色與型態
Sampler<動詞><資源><目的>GET Product Detail / POST Login首字大寫空格分隔
變數 (User Defined)udv_<語意>udv_baseUrl前綴辨識來源
CSV 欄位snake_caseproduct_id與 API JSON 對應
取樣結果變數resp_<語意>resp_token後續調用清楚
Propertiesenv.<key>env.host.api區分環境級別

4.3 推薦資料夾結構

測試資源與腳本放入版本控管(例:/perf-test):

perf-test/
  README.md                 # 測試目標與指標定義
  env/
    dev.properties
    qa.properties
    prod.properties.disabled
  data/
    users.csv
    products.csv
  scripts/
    ecommerce-login.jmx
    ecommerce-search.jmx
    modules/
      login-fragment.jmx    # Test Fragment (登入流程)
      search-fragment.jmx   # 可被多場景 include
  reports/
    2025-09-17-search-load-test/
      dashboard/            # HTML 報表輸出
      raw.jtl               # 原始結果
  bin/
    run-search-dev.bat
    run-search-dev.sh

4.4 Mermaid:資源關聯示意

graph LR A[Test Plan] --> B[Thread Group] B --> C{Modules / Include} C --> C1[Login Fragment] C --> C2[Search Fragment] A --> D[User Defined Variables] A --> E[Properties(env.*)] B --> F[CSV Data] B --> G[Samplers] G --> H[Assertions] G --> I[Listeners]

4.5 Thread Group 策略

策略使用時機參數重點風險
固定併發 (Classic Thread Group)基本負載或小測試Threads、Ramp-up、Loop不易模擬梯度升壓
階梯升壓 (Stepping / Ultimate)找臨界點、穩定拉升每階段增量、Hold 時間配置錯誤導致峰值過快
到達目標 RPS (Throughput Shaping + Concurrency)以 TPS/RPS 為主時間曲線、RPS 平臺需要插件支援
長時間穩定 (Soak)記憶體洩漏/資源穩定性延長 Duration、較低併發監控需同步進行

計算基礎:

併發數 (Concurrency) ≈ 每秒請求數 (RPS) * 平均回應時間(秒)

例如:目標 RPS=100,Avg RT=0.5s → 須約 50 Threads(可加 10~20% buffer)。

4.6 API 測試模板(可複製)

建立一個「模組化可重用」HTTP Sampler + 變數設計:

元件階層:
Test Plan
  -> User Defined Variables (udv_baseUrl, udv_authPath)
  -> Thread Group [TG]LoginAndQuery-100-Steady
    -> CSV Data Set Config (users.csv: username,password)
    -> HTTP Request: POST ${udv_authPath}/login
      Body(JSON): {"user":"${username}","pwd":"${password}"}
    -> JSON Extractor: token 目標路徑 $.data.token 儲存為 resp_token
    -> HTTP Header Manager: Authorization=Bearer ${resp_token}
    -> HTTP Request: GET ${udv_baseUrl}/api/products?id=${__CSVRead(products.csv,0)}
    -> Response Assertion: Contains "success"
    -> Listener: Summary Report

建議使用 JSON Extractor (新版) 取代舊式 Regular Expression 抽取 JSON。

4.7 指標定義(在 README 或測試說明中標準化)

指標說明典型門檻來源
Avg Response Time平均回應時間< 300ms(查詢類)Aggregate Report
P95 / P9995/99 百分位延遲P95 < 800msHTML Dashboard / JTL 分析
Error %失敗比例(Assertion+HTTP Code)< 1%Summary / Aggregate
Throughput每秒完成取樣數依需求Aggregate / Dashboard
Active Threads當前執行 threads是否穩定Backend Listener / Console
CPU / Memory / GC系統資源不飽和或趨勢平穩APM / 系統監控(外部)
DB Query Time後端瓶頸熱點查詢需 < 門檻APM / SQL Profiler

4.8 Include Controller 與 Test Fragment 模組化

拆分重複流程:

  1. 新建一個 login-fragment.jmx,在其中建立 Test Fragment(非 Thread Group)。
  2. 主測試計畫使用 Include Controller 引用該檔。
  3. 好處:
  • 多場景共用登入 / 取得 token
  • 異動集中維護
  • 減少複製貼上導致的版本漂移

4.9 變數與屬性作用域(預告)

本章先理解:User Defined Variables 在 Test Plan 載入時解析;CSV 在執行階段 per thread 讀取;抽取器(Extractor)在 Sampler 執行後注入。詳細優先序 Part 5 展開。

4.10 Mermaid:執行流程(含變數注入)

sequenceDiagram participant T as Thread participant CSV as CSV Data participant S1 as Login Sampler participant EX as JSON Extractor participant S2 as Query Sampler Note over T: 啟動 Thread → 載入 UDV / Properties T->>CSV: 讀取使用者帳密 T->>S1: POST /login (username,password) S1-->>EX: 回應 JSON EX-->>T: 設定變數 resp_token T->>S2: GET /products (Header: token) S2-->>T: 回應 + 驗證 Assertion

4.11 非 GUI 執行模板指令

jmeter -n -t scripts/ecommerce-search.jmx -q env/dev.properties -l reports/2025-09-17-search-load-test/raw.jtl -e -o reports/2025-09-17-search-load-test/dashboard

參數說明:

  • -n 非 GUI 模式
  • -t 指定 jmx 腳本
  • -q 載入環境屬性檔(可多次)
  • -l 輸出 jtl 結果檔
  • -e -o 生成 HTML Dashboard

Windows 批次檔範例(bin/run-search-dev.bat):

@echo off
set DATE=%DATE:~0,10%
set REPORT_DIR=reports\%DATE%-search-load-test
mkdir %REPORT_DIR%\dashboard 2>nul
jmeter -n -t scripts\ecommerce-search.jmx -q env\dev.properties -l %REPORT_DIR%\raw.jtl -e -o %REPORT_DIR%\dashboard

4.12 實務練習

目標:建立「登入 + 查詢」組合場景,100 使用者,Ramp-up 60 秒,持續 5 分鐘(可用 Loop Controller 搭配 Scheduler 或 Constant Throughput Timer 調整)。

  1. 建立資料檔 users.csvuser01,password01
  2. 建立 login-fragment.jmx 含 Login Sampler + JSON Extractor。
  3. 主場景引用 Include Controller。
  4. 加入 Search Sampler 使用 token。
  5. 設定 Assertion:HTTP 200 + 回應包含 "success"
  6. 非 GUI 執行並匯出 HTML 報表。
  7. 記錄:Avg / P95 / Throughput / Error%。

4.13 常見錯誤與陷阱

  • 在多 Thread Group 中各自複製登入邏輯 → 無法集中維護 → 請改 Test Fragment
  • 無斷言(Error%=0 但實際 500)→ 一律加至少 1 個成功判斷
  • CSV 未勾選 Recycle on EOF 且資料不足 → 後續使用者空值錯誤
  • Ramp-up 設為極低導致瞬間尖峰不符合真實行為
  • 將結果 Listener 全部保留在大壓測 → 記憶體爆滿

4.14 小結

你現在應能:

  • 制定命名規範與資料夾結構
  • 以模組化方式重用登入 / 查詢流程
  • 依據指標設定 Thread Group 策略
  • 使用非 GUI 模式生成報表

接下來第 5 章將處理「參數化、變數作用域與 Correlation」。


5. 參數化與資料驅動測試

5.1 為什麼需要參數化?

避免硬編(hardcode)提高可維護性、可重複性與環境可移植性:

  • 測試資料可批次更新(CSV)
  • 環境位址、認證、Port 改動不需修改多處 Sampler
  • 支援多場景共享登入 Token / 動態 ID
  • 強化可觀測性(變數命名即文件)

5.2 變數來源一覽

類型設定位置生效時機作用域常見用途
User Defined VariablesTest Plan / 元件屬性Test Plan 載入全域 (Test Plan)Base URL、共用路徑
CSV Data Set Config元件配置每 Thread 讀取該 Thread帳號、測試資料列
Properties (-q)外部檔 / 啟動參數啟動時全域唯讀 (可程式修改)環境 host、超時、開關
系統屬性 (-D)JVM 啟動啟動時全域編碼、憑證路徑
Extractor 變數回應處理後Sampler 執行後當前 ThreadToken、動態 ID、下一請求參數
函數助手 ${__time()}執行階段呼叫時呼叫點動態時間、亂數
JSR223 (Groovy)腳本執行階段依設定複雜邏輯、計算

5.3 CSV Data Set Config 深入

關鍵設定:

欄位說明建議
FilenameCSV 路徑相對於 JMX 或使用絕對路徑
File Encoding編碼UTF-8
Variable Names自訂欄名不填則讀第一列當標頭
Delimiter預設逗號可改 ;\t
Recycle on EOF?讀到結尾是否回捲壓力測試多循環時通常勾選
Stop thread on EOF?到結尾是否結束使用一次性資料時可啟用
Sharing Modehow threads share一般用 All Threads;避免重複可用 Current thread

避免常見錯誤:

  • 資料列不足 → Threads > CSV 行數且未回捲
  • 共享模式錯誤 → 多 Thread 爭用導致資料覆寫(應拆多檔或改 Sharing Mode)

5.4 User Defined Variables vs Properties

比較UDVProperties
設定方式GUI / Test Planuser.properties / -q 參數
讀取語法${變數名}${__P(key,default)} / ${__property(key,default)}
可修改執行中不建議改動可在 JSR223 透過 props.put()
使用時機腳本結構性常量跨腳本、環境差異

示例:在 env/dev.properties

env.host.api=https://dev.api.example.com
env.timeout.ms=3000

HTTP Request Server Name 可寫:${__P(env.host.api,https://fallback)}

5.5 Correlation(動態值提取)

動態值(Token、Session、動態 ID)需從回應中抽出再帶入下一請求。流程:

sequenceDiagram participant C as Client Thread participant S as Server C->>S: POST /login S-->>C: { token: "abc123", userId: 901 } Note over C: JSON Extractor token,userId C->>S: GET /orders?uid=${userId} S-->>C: 訂單列表 (驗證)

常用抽取器:

類型優點適用
JSON Extractor簡潔、支援 JSONPathREST/JSON API
Regular Expression Extractor通用HTML / 混合格式
CSS Selector ExtractorHTML DOMWeb 回應
JSR223 (Groovy)高度彈性複雜轉換

JSON Extractor 設定範例:

項目
Names of created variablesresp_token;resp_userId
JSONPath expressions$.token;$.user.id
Match Numbers1;1
Default ValuesN/A;0

5.6 API 回應範例與抽取

假設登入回應:

{
  "status":"success",
  "token":"eyJhbGciOi...",
  "user":{ "id":901, "roles":["USER","VIP"] },
  "expires":1694863200000
}

後續查詢訂單:GET /api/orders?uid=${resp_userId},Header:Authorization: Bearer ${resp_token}

5.7 函數助手(Functions)常用清單

函數用途範例備註
${__time(yyyyMMdd-HHmmss,)}產生時間字串報告識別尾逗號避免直接黏接
${__Random(1,1000,myRand)}指定區間亂數${myRand}需命名第三參數
${__UUID()}產生 UUID事務唯一鍵
${__groovy(UUID.randomUUID())}Groovy 自訂更複雜邏輯使用 JSR223 引擎

5.8 變數覆蓋與優先序(邏輯觀念)

從「最近、動態」到「最早、靜態」:

graph TD A[Extractor 變數] --> B[函數生成] B --> C[CSV Data] C --> D[User Defined Variables] D --> E[Properties (__P)] E --> F[系統屬性 -D]

解析順序說明:

  1. Test Plan 載入:UDV、Properties、系統屬性已可解析
  2. 執行階段:CSV 每 Thread/迴圈填入
  3. Sampler 回應後:Extractor 注入 -> 覆蓋同名早期值

命名防衝突建議:

  • 抽取變數加前綴:resp_ext_
  • CSV 來源加前綴:csv_
  • 只讀屬性加前綴:prop_(透過 props 轉存時)

5.9 Groovy / JSR223 活用

優先使用 JSR223 + Groovy(效能佳)。

設定腳本 cache:在 JSR223 元件勾選「Cache compiled script」以降低反覆編譯成本。

範例:動態組合查詢參數與基本驗證:

// 於 JSR223 PreProcessor
def id = vars.get('resp_userId') ?: '0'
def q = "status=ACTIVE&userId=${id}&ts=" + System.currentTimeMillis()
vars.put('queryString', q)

// 簡單防呆
if(!vars.get('resp_token')) {
  log.warn('token missing, will mark next request')
}

後續 Sampler Path:/api/orders?${queryString}

5.10 非 GUI 參數覆寫技巧

啟動時覆寫/補充 Properties:

jmeter -n -t scripts/ecommerce-search.jmx -q env/dev.properties -Jenv.host.api=https://override.dev.local -Jramp.users=200

在腳本使用:${__P(ramp.users,100)}

5.11 常見錯誤與排除

問題症狀原因解法
變數顯示未替換 ${var}回應或 Header 原樣未定義或拼字錯誤使用 Debug Sampler / View Results Tree
CSV 空白值Null / 空字串行尾多逗號或 BOM重新存 UTF-8 無 BOM
抽取失敗預期變數=DefaultJSONPath 不匹配用 JSON Path 線上測試
RPS 不穩定Threads 波動CSV IO 或 GC減少同步 IO、提升 Heap
Token 過期401 / 403 增加測試持續時間長加入定期重新登入流程

5.12 實務練習

建立「登入 → 查詢 → 建立訂單」場景:

  1. users.csv:帳號密碼 50 筆
  2. Login Sampler + JSON Extractor:resp_tokenresp_userId
  3. GET /products 使用 CSV 產品列表(products.csv
  4. POST /orders:Body 帶 ${resp_userId} 與隨機產品 ID
  5. Assertion:訂單建立回應包含 orderId
  6. 變數命名統一:resp_ 前綴
  7. -Jramp.users 傳入不同併發觀察 P95 差異

5.13 小結

你現在應能:

  • 使用 CSV/UDV/Properties 區分資料層級
  • 實作 Correlation(Token / ID 抽取)
  • 理解變數優先序與覆蓋策略
  • 使用 Groovy 動態組裝請求
  • 以啟動參數覆寫環境設定

下一章(第 6 章)將深入控制流程(Loop / If / Transaction / Throughput)與測試場景組合技術。


6. 控制器與流程控制 (Logic Controllers)

本章目標:

  • 理解各種邏輯控制器用途與差異
  • 建立可重用模組(Module / Include)
  • 使用 Transaction Controller 衡量事務耗時
  • 使用 Throughput / Runtime / If / Switch 控制動態路徑
  • 避免過度巢狀與維護風險
  • 實作多情境配比(例如 70% 瀏覽 / 20% 搜尋 / 10% 下單)

章節結構:

6.1 控制器分類概覽
6.2 Loop / While / ForEach 差異
6.3 If / Switch / Runtime Controller
6.4 Throughput Controller 與場景比例
6.5 Transaction Controller 與聚合分析
6.6 Module / Include Controller 模組化
6.7 Flow Control Action 中斷與暫停
6.8 控制器選擇決策矩陣
6.9 常見 anti-pattern 與重構
6.10 綜合實務案例
6.11 練習
6.12 小結

6.1 控制器分類概覽

類型控制器功能重點典型用途性能影響取代/互補
流程Loop Controller固定次數迴圈重複 API 呼叫While 當條件迴圈
流程While Controller條件為真則執行直到條件成立/變更取決於條件Loop 固定次數
流程ForEach Controller遍歷變數集合參數化多值後處理抽取配合 _g 索引
邏輯If Controller判斷布林條件Token 有效才呼叫Switch 互補
邏輯Switch Controller基於名稱/索引選一支路徑多場景分支If 多條件時複雜
配比Throughput Controller依百分比或總次數行為比例模擬Runtime 控時間
時間Runtime Controller限制子節點執行時長暖機 / 短測段Scheduler 層級控制
分組Transaction Controller量測子步驟總耗時交易耗時統計添加額外聚合僅覆蓋 ROI 部分
模組Module Controller引用 Test Fragment重用步驟Include 跨檔案
模組Include Controller引入外部 JMX共用登入、初始化輕微 IOModule 同檔內
控制Flow Control ActionBreak / Continue / Pause動態中止While 條件提前設計

Mermaid:控制器作用層級概念圖:

graph TD A[Test Plan] --> B[Thread Group] B --> C[Throughput Controller] C --> D[Transaction Controller] D --> E[Sampler 1] D --> F[Sampler 2] B --> G[If Controller] G --> H[Sampler 3] B --> I[Module Controller -> Fragment] I --> J[Login Steps]

6.2 Loop / While / ForEach 差異

對照LoopWhileForEach
驅動型態固定次數布林條件集合元素
結束條件次數達標條件為假遍歷完
風險次數估錯無窮迴圈變數未配對
常見用途重試固定次等待狀態變化處理抽取列表

最佳實務:

  • While 條件使用明確變數,如 ${__groovy(vars.get('done')=='true')}
  • 加入最大迴圈防護:可在條件中遞增計數達上限跳出
  • ForEach 搭配 JSON Extractor 使用 names + matchNr 生成 var_1..var_n

While 監控狀態範例(輪詢直到成功或超時):

// JSR223 PreProcessor (設於 While 子節點第一個 Sampler 前)
def cnt = (vars.get('pollCnt') ?: '0').toInteger() + 1
vars.put('pollCnt', cnt.toString())
if (cnt > 20) { // 超過 20 次跳出
  vars.put('done','true')
}

While 條件:${__groovy(vars.get('done')=='true')} 然後選擇「Interpret Condition as Variable Expression」。

6.3 If / Switch / Runtime Controller

控制器核心判斷使用語法常見場景注意
If布林結果${JMeterThread.last_sample_ok} / Groovy 表達式依上一請求成功才進行下一步避免複雜嵌套
Switch匹配名稱或索引下方列的子節點名稱多路徑(例如操作型)未匹配則不執行任何
Runtime時間上限 (秒)設定 Duration暖機 / 短測抽樣與 Scheduler 請勿衝突

Runtime Controller 適合:快速抽樣 API 行為特徵,不用等整個測試結束。

6.4 Throughput Controller 與場景比例

模式:

  • Percent Execution:每個 Thread 依百分比機率執行
  • Total Executions:跨 Threads 總次數上限

模擬 70% 瀏覽 / 20% 搜尋 / 10% 下單:

graph LR TG[Thread Group] --> A[Throughput 70% Browse] TG --> B[Throughput 20% Search] TG --> C[Throughput 10% Order]

注意:Percent 模式是獨立評估每個子控制器,不會自動保證總合精確比例(統計上接近)。需嚴格比例時應使用自訂亂數路由(JSR223 + Switch)。

亂數路由精確實現(總和 100):

// JSR223 Sampler 於 Thread Group 開頭
def r = (int)(Math.random()*100)
def path = r < 70 ? 'BROWSE' : (r < 90 ? 'SEARCH' : 'ORDER')
vars.put('scenario', path)

Switch Controller 名稱對應:BROWSESEARCHORDER

6.5 Transaction Controller 與聚合分析

用途:將多個 Sampler 視為單一「事務」以衡量端到端耗時(例如:搜尋 + 過濾 + 載入結果)。

設定建議:

  • 勾選「Generate parent sample」:在報表中得到整體事務一筆紀錄
  • 保持內部 Sampler 原始:方便分析細節瓶頸
  • 事務粒度避免過大(>10 個 Sampler)

常見錯誤:

  • 過度巢狀(Transaction 包 Transaction)→ 難以判讀
  • 把單一 Sampler 包成 Transaction → 無意義

6.6 Module / Include Controller 模組化

控制器資料來源使用時機優點侷限
Module Controller參考同 Test Plan 下 Test Fragment重用登入、初始化即時同步、易調整侷限單檔
Include Controller外部 JMX跨腳本共享(登入、前置建立資料)可拆分團隊協作需要路徑管理

Test Fragment:僅供引用,不會自行執行,通常存放公共步驟(Login、Setup Token、Health Check)。

結構示例:

graph TD TP[Test Plan] --> TG[Thread Group] TP --> FR1[Test Fragment Login] TP --> FR2[Test Fragment Browse] TG --> M1[Module -> Login] TG --> M2[Module -> Browse]

6.7 Flow Control Action 中斷與暫停

功能:在執行期強制控制流程:

動作說明常見用途
Stop停止當前 Thread致命錯誤(登入失敗)
Stop Now立即停止(不等清理)緊急中止
Pause暫停指定毫秒節奏控制(避免打爆系統)
Break跳出最近的控制器提前結束迴圈
Continue繼續下一迭代忽略當前失敗分支

6.8 控制器選擇決策矩陣

需求推薦控制器解釋附註
重複 N 次Loop固定次數最簡潔不需 While
等待條件成立While動態輪詢加超時保護
多分支互斥Switch清晰路徑名稱對應
條件有/無則執行If快速判斷避免巢狀
指定執行比例Throughput百分比模擬精準需自訂亂數
限制執行時間Runtime子流程限時與上層 Scheduler 區隔
聚合耗時Transaction整體端到端避免過大
重用步驟Module / Include模組化過多碎片化風險

6.9 常見 Anti-pattern 與重構

問題模式描述風險重構策略
過深巢狀4+ 層控制器嵌套可讀性差扁平化:抽出 Test Fragment
Transaction 疊套交易內再包交易指標混淆僅保留外層關鍵事務
百分比控制器堆疊多個 Throughput 期待加總 100%實際偏差改自訂亂數 + Switch
While 無上限條件永不成立無窮迴圈加計數器 + 最大值
Include 過度拆檔十多個小 JMX管理成本高合併相近 Fragment

6.10 綜合實務案例

目標:模擬電商行為比例(瀏覽 65% / 搜尋 20% / 下單 10% / 其餘健康檢查 5%),並量測「下單事務」端到端耗時。

結構:

graph TD TG[Thread Group] TG --> P1[JSR223 路由變數 scenario] TG --> SW[Switch Controller] SW --> BR[Browse Flow (Module)] SW --> SR[Search Flow (Transaction)] SW --> OR[Order Flow (Transaction)] SW --> HC[Health Check (If)]

路由變數腳本(置於第一個 JSR223 Sampler):

def r = (int)(Math.random()*100)
def scn = r < 65 ? 'BROWSE' : (r < 85 ? 'SEARCH' : (r < 95 ? 'ORDER' : 'HEALTH'))
vars.put('scenario', scn)

Switch Controller 子節點命名需與 scenario 值一致。

Order Flow Transaction:

  • Step1: 加入購物車
  • Step2: 建立訂單
  • Step3: 取得訂單狀態

報表觀察指標:

  • ORDER Transaction 平均 / P95
  • ORDER 流程內部哪個 Sampler 最慢(可能是建立訂單 API)

6.11 練習

練習目標:建立「登入 → 根據使用者身分(VIP / 一般)走不同場景」:

  1. 登入抽取 resp_userType
  2. 使用 If:resp_userType == 'VIP' 走 VIP Fragment
  3. 其他走一般 Fragment
  4. VIP Fragment 內包 Transaction(複合查詢)
  5. 一般流程使用 Loop 重複瀏覽 3 次
  6. 加入 Flow Control Action 在 VIP Fragment 中條件不符時 Break

挑戰延伸:改用 Switch + 路由變數(將 VIPNORMAL 標準化)。

6.12 小結

你現在應能:

  • 正確選擇 Loop / While / ForEach 控制流程
  • 使用 If / Switch / 自訂亂數 建立分支路由
  • 用 Throughput / Transaction 建模比例與端到端耗時
  • 用 Module / Include 模組化共用步驟
  • 用 Flow Control Action 安全中斷或節奏控制
  • 辨識並重構控制器 Anti-pattern

下一章(第 7 章)將深入 Assertion:如何驗證結果、分類錯誤、控制失敗策略與提升報表可解讀性。


7. Assertion 斷言與結果驗證策略

本章目標:

  • 正確選擇 Assertion 類型 (狀態碼/Body/JSON/時間/大小)
  • 控制失敗策略:Fail Fast vs 寬鬆收集
  • 建立錯誤分類(功能錯 / 性能錯 / 資料錯 / 環境錯)
  • 動態門檻設定(環境差異 / 基準波動)
  • 減少過度斷言導致的性能負擔

章節結構:

7.1 為什麼需要明確斷言策略
7.2 常見 Assertion 類型比較
7.3 狀態碼與錯誤分類
7.4 JSON / 正則 / XPath / Size 使用情境
7.5 Duration / SLA 驗證與 P95 判讀
7.6 動態門檻 (Baseline / Properties) 7.7 失敗策略:Fail Fast vs 收集模式
7.8 減少斷言開銷的最佳實務
7.9 錯誤訊息標準化(Log 與報表對齊)
7.10 實務案例:登入 + 查詢 + 下單
7.11 練習
7.12 小結

7.1 為什麼需要明確斷言策略

沒有斷言 = 僅測速度;有錯誤卻視為成功會得出失真指標。過多斷言又會:

  • 增加 CPU/記憶體(特別是大型回應解析)
  • 造成回應樹檢視困難(失敗訊息冗長)
  • 增加調校門檻(門檻硬編)

目標:最少且關鍵、可維護、可調整。

7.2 常見 Assertion 類型比較

類型功能適用不適用性能影響備註
Response Code驗證 HTTP 狀態碼一般 API非 HTTP基礎必要
Response Assertion (字串)包含 / 不包含小型文字片段超大 JSON可用於錯誤訊息關鍵字
JSON AssertionJSONPath 評估結構化 JSON巨大 / 流式配合抽取結果再驗證
Duration Assertion單請求耗時門檻SLA 單筆長事務端到端避免與 Transaction 重複
Size Assertion回應長度異常短/長檢測長度波動大粗略防禦
JSR223 Assertion自訂邏輯複合條件過度濫用取決於腳本可集中整理失敗訊息
XPath AssertionXML 檢查SOAP/XMLJSON-only中偏高僅必要時用

7.3 狀態碼與錯誤分類

分類矩陣:

類別標準例子分析方向報告呈現
功能錯 (Functional)4xx / 業務邏輯碼錯400, 422請求組裝 / 驗證邏輯標註為錯誤計數
系統錯 (System)5xx500, 502後端穩定性 / 資源高優先調查
資料錯 (Data)回應字段缺 / 值錯userId=null測試資料 / Correlation以字串 Assertion 捕捉
性能錯 (SLA)耗時 > 門檻> 800ms容量 / 指數成長匯入報表 KPI
環境錯 (Env)DNS / 連線失敗Timeout網路 / 設定檔啟動前健康檢查

Response Assertion(字串包含)配置技巧:

  • 包含:"status":"success"
  • 不包含:"error""Exception"
  • 忽略大小寫:勾選 Ignore Status(依版本功能)

7.4 JSON / 正則 / XPath / Size 使用情境

場景推薦理由替代
結構化 JSONJSON Assertion可讀性好JSR223 Groovy
同時驗多欄位JSR223 Assertion一次判斷 + 聚合訊息多個 JSON Assertion
HTML/混合格式Regular Expression彈性CSS/XPath
XML/SOAPXPath Assertion原生結構Regex(較脆弱)
只需保底Size Assertion快速檢測異常字串包含

JSR223 Assertion 範例(集中輸出):

def json = new groovy.json.JsonSlurper().parseText(prev.getResponseDataAsString())
def errors = []
if(json.status != 'success') errors << 'status!=success'
if(!json.user?.id) errors << 'user.id missing'
if(json.durationMs && json.durationMs > 800) errors << 'duration SLA fail'
if(errors) {
    AssertionResult.setFailure(true)
    AssertionResult.setFailureMessage(errors.join(';'))
}

7.5 Duration / SLA 與 P95 判讀

單筆 SLA:用 Duration Assertion,例如:< 800 ms。缺點:尖峰抖動可能造成大量失敗。建議配合:

  • 報表中觀察 P95/P99 是否穩定
  • 使用 Transaction Controller 衡量完整流程 SLA
  • 允許少量超標(報表層面評估,而非全部標 Fail)

策略:單筆超時記錄但不 Fail 整測,於報表彙整(以聚合報表/HTML Dashboard 判讀)。

7.6 動態門檻 (Baseline / Properties)

避免硬編:利用 properties + 前置抽取基準。

  1. 先跑基準測得 login.avg=320
  2. 設定門檻:login.sla.ms = baseline * 1.5
  3. 啟動前寫入 baseline.properties

JSR223 Assertion 動態門檻:

def base = props.get('login.baseline.ms')?.toInteger() ?: 300
def limit = (base * 1.5) as int
def rt = prev.getTime()
if(rt > limit) {
  AssertionResult.setFailure(true)
  AssertionResult.setFailureMessage("login rt=${rt} > limit=${limit}")
}

7.7 失敗策略:Fail Fast vs 收集模式

策略行為優點風險使用時機
Fail Fast關鍵錯立即停止 Thread/測試快速回饋可能少收集證據嚴重功能錯 / 環境掛掉
收集模式錯誤記錄但不中斷全面資料產生大量噪音壓測長時間觀察穩定性
混合關鍵錯 Fail Fast + 一般錯收集平衡複雜度高中大型壓測

建議:用 Flow Control Action + 變數旗標控制提前停止某流程。

7.8 減少斷言開銷的最佳實務

  • 只對必要 Sampler 加 Assertion(高價值 API)
  • 避免對巨大回應反覆用 Regex(改 JSONPath + 限縮抽取)
  • 合併多個欄位驗證於單一 JSR223(降低管理成本)
  • JSON 解析可重用 groovy.json.JsonSlurper 實例(或快取字串)
  • 測試初期可開啟詳細,穩定後減少低價值驗證

7.9 錯誤訊息標準化

格式範例:[TYPE=SLA][API=login][RT=920][LIMIT=800]{"type":"DATA","field":"user.id"}

標準化好處:

  • 日誌可用工具聚合統計類型比例
  • 減少人工閱讀成本
  • 可輸出為後處理報表(例如自訂 Parser)

7.10 實務案例:登入 + 查詢 + 下單

需求:驗證登入成功、查詢結果含商品、下單回傳訂單編號且總耗時 < 2500ms。

設計:

  1. Login Sampler:Response Code + JSON Assertion(status=success
  2. Query Products:字串包含 "items" + Size > 200 bytes
  3. Order Transaction:使用 Transaction Controller 包含建立 / 查詢狀態兩步
  4. Transaction SLA:不在 Sampler 直接 Fail,改報表層觀察 P95 < 2500
  5. 若 Login 失敗 → Flow Control Action 停止當前 Thread

額外:JSR223 Assertion 聚合錯誤:

def err = []
def json = new groovy.json.JsonSlurper().parseText(prev.getResponseDataAsString())
if(!json.orderId) err << 'missing orderId'
if(json.total && json.total < 0) err << 'total negative'
if(err) { AssertionResult.setFailure(true); AssertionResult.setFailureMessage(err.join('|')) }

7.11 練習

練習題:為「登入 → 搜尋 → 下單」腳本新增:

  1. 登入:狀態碼 200 且 JSON token 不為空
  2. 搜尋:回應包含關鍵字 "price" 且大小 > 300 bytes
  3. 下單:回應 JSON orderIdstatus='CREATED'
  4. 端到端(Transaction)P95 需 < 3000ms(於報表分析)
  5. 過載時允許 2% 內 SLA 超標(報表手動計算)

延伸:以 properties order.sla.ms=2800 動態驅動 JSR223 Assertion。

7.12 小結

你現在應能:

  • 根據場景挑選適當 Assertion 類型
  • 實作錯誤分類與訊息標準化
  • 動態設定 SLA 門檻避免硬編
  • 平衡 Fail Fast 與收集完整證據
  • 降低不必要解析開銷

下一章(第 8 章)將解析報表與指標解讀與常見誤區。


8. 報表與結果分析

本章目標:能正確解讀常見報表(Summary / Aggregate / HTML Dashboard),理解 P95 與平均數差異、錯誤率來源分類、指標趨勢與異常型態,並建立基準值 (Baseline) 與版本對比流程。

適用情境:功能腳本驗證完成後的效能 / 負載 / 壓力 / 回歸測試分析。

8.1 核心指標再回顧

指標定義為什麼重要常見誤區
Avg (平均)所有樣本平均回應時間粗略概念平均被極端值拉低/拉高
Median (P50)50% 請求 <= 該時間中位穩定性常被忽略但可看分佈偏態
P90/P95/P99百分位延遲使用者體感、SLA只看 P95 忽略尾端肥尾問題
Min/Max極值排查尖峰只看 Max 易受偶發干擾
Throughput (Req/s)單位秒完成的請求數系統處理能力與使用者數混淆
Error%失敗取樣比率穩定性未分類錯誤來源
Active Threads當前執行中的虛擬用戶數證明升壓成功與使用者行為模型脫節
Bytes / KB/sec每秒資料量對頻寬/壓縮影響忽視傳輸瓶頸

判讀原則:延遲看 P95 + P99 是否穩定、吞吐需搭配 Active Threads 曲線是否平穩、Error% 需拆分類型後再判斷。

8.2 Summary / Aggregate Report 差異

報表適用優點限制
Summary Report快速觀察指標總覽輕量、即時不含百分位細部、缺樣本分佈
Aggregate Report百分位觀察 (P90/P95)可導出 CSV未含圖形化趨勢
Aggregate Graph圖表化直覺比較高樣本量時耗資源
View Results Tree功能驗證 / Debug可看原始回應不應在高負載啟用

最佳實務:腳本調試階段可用 View Results Tree;正式負載測試僅保留必要 Listener(Summary + Backend Listener 或直接用 non-GUI + HTML Dashboard)。

8.3 HTML Dashboard 產出與指標

產出方式(非 GUI 完成後):

jmeter -g results.jtl -o reports/html

或於執行時直接產出:

jmeter -n -t test.jmx -l results.jtl -e -o reports/html

主要頁面重點:

區塊指標解讀重點
Dashboard Index各模組入口入口導覽
Statisticsmin/avg/median/90%/95%/99%關鍵性能聚合
Errors錯誤類型/比例快速分類來源
Active Threads Over Time登/降壓是否平滑驗證腳本模型
Response Times Over Time是否出現尖峰分析抖動時段
Response Time Percentiles尾延遲趨勢是否惡化
Throughput vs Response Time負載 vs 延遲關係飽和點預兆

8.4 百分位數 (Percentile) 判讀策略

百分位顯示尾部延遲:

現象可能原因行動風險
P95 與 Avg 接近延遲分佈集中可接受尾端穩定
P95 遠高於 Avg長尾/偶發延遲找尖峰時段使用者體感不佳
P99 爆炸性拉高Resource/GC/Lock關聯 GC log / profilingSLA 風險
百分位曲線上揚壓力提升後退化尋找臨界閾值容量不足

可用「Baseline vs Current」比較:若 P95 增幅 > (基準 * 1.15) 則標記黃燈;>1.3 標記紅燈。

8.5 Error% 分類與來源拆解

分類維度:

  1. 功能錯誤(狀態碼 4xx/5xx、商業邏輯返回)
  2. Assertion SLA 超時(自訂性能門檻)
  3. 網路/連線類(連線重設 / 超時 / DNS)
  4. 腳本錯誤(變數為空、未成功登入造成後續失敗)

動作:於 JSR223 Assertion 將錯誤統一前綴,如:FUNC_ / SLA_ / NET_ / SCRIPT_,利於報表後分組。

8.6 建立 Baseline 與版本對比流程

推薦檔案:baseline.properties(收錄上一穩定版本指標)。

流程:

flowchart LR A[測試執行完成] --> B[擷取 HTML Dashboard 指標] B --> C[寫入 current.properties] C --> D{與 baseline 差異} D -- 門檻內 --> E[標記 PASS] D -- 超出門檻 --> F[標記 WARN/FAIL] F --> G[建立 JIRA / Issue] E --> H{需要更新 baseline?} H -- 是 --> I[人工審核後覆寫 baseline] H -- 否 --> J[保留觀察]

差異比較(簡化示例):

指標baselinecurrent變化判定
P95(ms)780810+3.8%
P99(ms)11001320+20%黃 (觀察)
Error%0.6%1.4%+0.8pp紅 (調查)
Throughput930950+2%

8.7 異常模式(Pattern)辨識

模式圖像特徵可能原因動作
鋸齒型延遲延遲上下規律震盪GC Minor / 自動縮擴容對應 GC log / 平台事件
階梯型上升延遲階段式升高連線池累積 / Thread 飽和檢查池大小 / thread dump
週期性尖峰固定週期突增CRON 批次 / Cache 失效與排程對時段
線性上升延遲隨時間穩定攀升記憶體漏 / 資源未釋放長時間 Soak 驗證
Active Threads 波浪無法維持穩定併發測試端資源不足分散節點 / 降 thread

8.8 Active Threads 與 Throughput 關聯

期望情境:Active Threads 按 Ramp-up 平滑上升並在 plateau 維持,Throughput 對應提升後趨於穩定。

偏差判讀:

現象解讀可能根因
Active 線性上升但 Throughput 平系統達飽和CPU / DB / IO 鎖競爭
Active 平穩但 Throughput 抖動後端不穩 / 網路單節點健康問題
Throughput 遲滯上升暖機/JIT/Cache前幾分鐘不列入統計

8.9 實務:指標判讀工作表

可建立一個分析模板(每次測試填寫):

項目觀察結論行動
P95 是否穩定760~790ms穩定
P99 是否異常升至 1320ms尾延遲拉長查看慢查詢
Error% 類型FUNC_0.4% / SLA_0.6%SLA 問題居多調整緩存策略
Active Threads平穩 500模型正常
Throughput950±20穩定
GC 行為Minor GC 規律可接受監控 Full GC

8.10 自動化輸出建議

腳本化擷取 HTML Statistics 表:

grep 'Transactions' -n reports/html/statistics.json > /dev/null # 示意:實際可用 jq 解析
jq '.Total | {samples:.sampleCount,avg:.meanResTime,p95:.pct95ResTime,error:.errorPct}' reports/html/statistics.json > stats-current.json

與 baseline JSON 對比(Pseudo):

jq -s '.[0] as $base | .[1] as $cur | {p95_delta: (($cur.p95-$base.p95)/$base.p95)}' baseline.json stats-current.json

退出碼策略:若 p95_delta > 0.15error > 0.02 則退出碼 1(Fail)。

8.11 小結

你現在應能:

  • 區分各類報表用途並在正式測試中減少 Listener 開銷
  • 正確解讀 P95 / P99 與平均差異,避免只看平均
  • 透過百分位與 Active Threads / Throughput 交叉判讀飽和點
  • 建立 Error% 分類與 Baseline 對比流程
  • 識別常見異常模式並規劃後續調查方向

下一章(第 9 章)將整理效能最佳實務與腳本 / 系統層雙向調優建議。

9. 效能最佳實務

本章聚焦於「如何讓測試結果可信、可重複、可擴充」以及「如何降低腳本與執行環境本身的性能干擾」,並涵蓋容量規劃、資料治理、觀測與調優流程。

9.1 Thread 數 vs RPS (Requests Per Second) 推估

估算步驟:

  1. 先以小規模 (e.g. 20 threads) 實測單使用者平均 think time 與回應時間。
  2. RPS 近似:Threads / (ResponseTime + ThinkTime)(秒)。
  3. 若需求 RPS 為 200,且單行為 (RT+Think) 約 1.2s,理論 Threads ≈ 240。再考量:
  • 長尾延遲 → 需加 10~20% buffer。
  • 排程/外部依賴不穩定 → 避免一次極限壓滿。

對照表(示例):

目標 RPS實測 RT(ms)Think(ms)估算 Threads建議 Threads (含 buffer)
503003003035
1004003007080
200500700150180
500450550275330

注意:當系統接近飽和,RT 增加會反過來要求更多 Threads → 形成誤導。需用漸進升壓曲線找拐點。

9.2 升壓模式與 Ramp-up 策略

推薦:階梯式 (Stair-step) 或 線性漸進。避免瞬間 0→1000。

模式優點風險適用
線性漸進平滑觀察指標若步長太小耗時長探索臨界值
階梯式清晰對比每級表現步階過大易錯過拐點容量預估
突刺 (Spike)模擬突增流量若太猛易誤判壓力抗性
恢復 (Spike Recovery)見系統恢復力複雜高可用測試

9.3 暖機 (Warm-up) 與資料清洗

避免將 JIT 編譯、Cache 建立、連線池預熱納入正式統計。方式:

jmeter -n -t test.jmx -l warmup.jtl -Jduration=120 -Jwarmup=true # 暖機階段
jmeter -n -t test.jmx -l run.jtl -Jduration=600                 # 正式階段

或於單次執行後裁剪初段樣本(HTML Dashboard 觀察 Active Threads 已穩定後起算)。

9.4 減少腳本端資源干擾

項目說明建議
ListenerGUI 可視化耗 CPU/記憶體非 GUI 僅保留必要取樣寫檔
View Results Tree只用於調試負載測試時移除
Regex 過多大字串多重匹配改 JSON Extractor / 精準表達式
重複字串組裝Groovy 重複 concat以函式/變數共用
日誌等級DEBUG 過高僅在排錯短期開啟

9.5 測試資料生命週期與汙染防護

原則:可重複、可追蹤、避免交叉干擾。

策略:

  1. 讀取模式:CSV Data Set → 每 thread 專用 vs 共用(避免主鍵衝突)。
  2. 資料結束行動:不足時是否循環?若不循環必須監控樣本數 vs 資料量。
  3. 測試後清理:建立清理腳本還原資料(訂單、暫存表)。
  4. 敏感資料:去識別化 / 假資料生成(以 Faker / 事前 SQL 產出)。

9.6 脚本組織與模組化回顧 (與第 4 / 6 章呼應)

分層:

層級內容工具
Test Plan全域屬性載入、前置初始化Properties / UDV
FragmentLogin / HealthCheck / 通用 HeaderTest Fragment + Module Controller
Flow交易流程:登入→瀏覽→查詢→下單Transaction Controller
ExtractorToken / 參照 IDJSON / Regex Extractor
AssertionSLA / 功能驗證Response + JSR223

9.7 系統資源觀測建議 (外部協同)

資源指標工具判斷焦點
CPU使用率 / Run Queuetop / sar / node_exporter是否長期 >80%
記憶體Heap / RSS / GC 次數jstat / jmap / APMFull GC / Leak
磁碟 / IOIOWait / LatencyiostatIOWait > 10% 持續
DBQPS / 慢查詢 / 連線池APM / slow log鎖、排序、掃描
網路RTT / Retrans / 帶寬ss / netstat / APM重傳或延遲飆升

測試報告需交叉引用:延遲異常時是否對應 CPU 飆升或 DB 慢查詢激增。

9.8 性能退化 (Regression) 早期偵測

做法:於 CI 中每日(或每合併)執行「輕量基準測試」(Smoke Performance)。指標:小樣本 3~5 分鐘 / 50 threads。

策略表:

指標門檻行為
P95 變動> +15%標黃,通知觀察
Error%> 1%標紅,阻擋合併
Throughput 下降> 10%標黃,人工確認

9.9 GC 與 JVM 觀察(若系統為 JVM)

重點:

  1. Minor GC 頻率規律且停頓 < 100ms → 正常。
  2. Full GC 出現頻率 > 1 次/10 分鐘需調查(Heap、物件膨脹)。
  3. 尾延遲暴增時對比 GC log 時戳。

示例啟動(被測系統)建議:

-Xms4G -Xmx4G -XX:+UseG1GC -XX:MaxGCPauseMillis=300 -Xlog:gc*,safepoint:file=gc.log:time,uptime,level,tags

9.10 常見瓶頸快速定位路徑

徵象初判下一步
延遲遞增 + CPU 高計算瓶頸Profiling / Flame Graph
延遲遞增 + CPU 低外部 IO/鎖等待Thread dump / DB 慢查詢
Error% 增 + P95 上升回應錯誤導致重試錯誤類型分類
Throughput 平 + Threads 上升達飽和 / 競爭系統 thread / pool 大小
P99 抖動長尾鎖 / GC分析特定慢請求樣本

9.11 測試環境一致性與可重複性

風險:測試環境規模 < 正式 → 指標過於樂觀;或多服務共享環境 → 背景噪音。

治理:

  1. 版本固定(Image Tag / Commit Hash)。
  2. 基礎設施參數記錄(CPU/記憶體/節點數)。
  3. 測試執行前健康檢查(Login / Ping / 依賴服務)。
  4. 測試期間禁止非測試人員變更。

9.12 Anti-pattern 與改進建議

Anti-pattern影響改進
單一巨大 JMX 混合所有場景維護困難 / 調試混亂拆分場景 + Include/Fragment
任意加 Thread 追 RPS導致非線性延遲先剖析單請求耗時構成
不分功能錯誤與 SLA 錯誤誤判穩定性錯誤前綴分類
無暖機直接統計指標失真丟棄初段樣本
CSV 不夠仍循環資料污染監控剩餘行 / 預生成資料
過度依賴 GUI資源干擾大非 GUI + 報表後處理

9.13 小結

你現在應能:

  • 以科學方式估算 Threads 與 RPS 並建立升壓策略
  • 區分暖機與正式統計,控制測試端干擾
  • 治理測試資料生命週期與避免汙染
  • 與系統/DB/GC 觀測數據交叉分析瓶頸
  • 建立早期性能退化偵測與 Anti-pattern 清單

下一章(第 10 章)將聚焦 CI/CD 整合:自動執行、門檻判定與報告發佈。

10. CI/CD 與自動化整合

目標:將性能腳本納入持續整合流程,於每次合併或排程執行輕量/回歸性能測試,自動產生報表、比較基準並回饋狀態(Pass / Warn / Fail)。

10.1 測試類型在 Pipeline 的定位

類型觸發時機時間限制目的例子
Smoke PerformancePR / 每次合併3~5 分鐘快速退化監測50 threads / 3 分鐘
Daily Baseline每日排程10~20 分鐘更新趨勢線200 threads / 10 分鐘
Release Qualification發版前30~60 分鐘SLA 確認500 threads / 20 分鐘
探索/壓力手動觸發不限容量/崩潰點階梯升壓 100→1000

10.2 非 GUI 執行標準化腳本

建立 perf-test/bin/run-test.sh(Linux/Mac)與 run-test.bat(Windows),統一參數:

#!/usr/bin/env bash
set -euo pipefail
SCENARIO=${1:-login}
ENV=${2:-dev}
TS=$(date +%Y%m%d-%H%M%S)
OUT=perf-test/reports/${TS}-${SCENARIO}-${ENV}
mkdir -p "$OUT"
jmeter -n -t perf-test/scripts/${SCENARIO}.jmx \
  -q perf-test/env/${ENV}.properties \
  -l "$OUT/results.jtl" -e -o "$OUT/html" \
  -Jbuild.sha=${GIT_COMMIT:-local} || EXIT_CODE=$?
python perf-test/tools/eval.py "$OUT" || EXIT_CODE=$?
exit ${EXIT_CODE:-0}

重點:由腳本本身統一輸出目錄命名規則,利於後續收集 artifacts。

10.3 退出碼策略 (Exit Code Policy)

條件行為Exit Code
Error% > 2%Fail1
P95 增幅 > +30% (相對 baseline)Fail1
P95 增幅 15%~30%Warn (不中斷)0
Error% 1%~2%Warn0
缺少結果檔 / 解析失敗Fail2

Warn 可用 pipeline 訊息或標籤通知人工審核。

10.4 基準值 (Baseline) 檔與差異比較

baseline.json(示例):

{
  "scenario":"login", "p95":780, "errorPct":0.8, "throughput":930
}

stats-current.json(從 HTML Dashboard statistics.json 解析精簡):

{ "scenario":"login", "p95":820, "errorPct":1.1, "throughput":950 }

比較腳本(Pseudo):

p95_base=$(jq .p95 baseline.json); p95_cur=$(jq .p95 stats-current.json)
delta=$(awk -v b=$p95_base -v c=$p95_cur 'BEGIN{printf("%.2f", (c-b)/b)}')
echo "P95 Delta=${delta}"
if awk -v d=$delta 'BEGIN{exit !(d>0.30)}'; then echo FAIL; exit 1; fi

10.5 GitHub Actions 範例 (Smoke Performance)

.github/workflows/perf-smoke.yml

name: Perf Smoke
on:
  pull_request:
    paths:
      - 'perf-test/**'
  workflow_dispatch:
jobs:
  smoke:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '17'
      - name: Cache JMeter
        uses: actions/cache@v4
        with:
          path: ~/.jmeter
          key: jmeter-5.6.3
      - name: Download JMeter
        run: |
          if [ ! -d ~/.jmeter/apache-jmeter-5.6.3 ]; then \
            curl -sSL https://downloads.apache.org/jmeter/binaries/apache-jmeter-5.6.3.tgz | tar zx -C ~/.jmeter; fi
          echo "JMETER_HOME=$HOME/.jmeter/apache-jmeter-5.6.3" >> $GITHUB_ENV
      - name: Run Smoke Scenario
        run: |
          export PATH=$JMETER_HOME/bin:$PATH
          bash perf-test/bin/run-test.sh login dev
      - name: Archive Report
        uses: actions/upload-artifact@v4
        with:
          name: perf-report
          path: perf-test/reports/*/html

10.6 Jenkins Pipeline 範例

Jenkinsfile

pipeline {
  agent any
  options { timestamps() }
  environment { JMETER_VERSION = '5.6.3' }
  stages {
    stage('Checkout') { steps { checkout scm } }
    stage('Setup JMeter') {
      steps {
        sh '''
        if [ ! -d tools/apache-jmeter-$JMETER_VERSION ]; then \
          curl -sSL https://downloads.apache.org/jmeter/binaries/apache-jmeter-$JMETER_VERSION.tgz | tar zx -C tools; fi
        export PATH=$PWD/tools/apache-jmeter-$JMETER_VERSION/bin:$PATH
        '''
      }
    }
    stage('Run Smoke') {
      steps {
        sh 'bash perf-test/bin/run-test.sh login dev'
      }
    }
  }
  post {
    always { archiveArtifacts artifacts: 'perf-test/reports/**', fingerprint: true }
    failure { mail to: 'perf-alerts@example.com', subject: 'Perf Smoke Fail', body: 'Check Jenkins job.' }
  }
}

10.7 多環境參數化與組態管理

方式說明範例
Properties 檔每環境基礎組態dev.properties / stage.properties
-J 覆寫臨時調整單一鍵-Jusers=100
-q 多檔疊加屬性層-q base.properties -q stage.properties
CI 變數注入Secrets / TokenActions Secrets / Jenkins Credentials

避免:把 Token / 密碼寫入 Git。改用環境變數於 run-test.sh 注入再轉為 JMeter property。

10.8 Artifacts 與報告留存策略

等級保存內容保存週期適用
PR SmokeHTML Dashboard、stats-current.json7 天快速檢視
DailyDashboard + 比較 diff30 天趨勢觀察
Release完整 raw JTL + GC log 摘要永久/半年合規 / 稽核

可再另行產出:perf-index.json 聚合每次 run 的 p95/error%、生成趨勢圖。

10.9 Baseline 自動更新準則

避免「自動覆蓋導致真實退化被吞噬」。

條件行為
P95 改善 ≥ 10% 且 Error% 未上升允許候選 baseline(需人工標記)
波動 < ±5%不更新(避免噪音)
P95 退化不更新 baseline

流程:人工審核 stats-current.json → 手動 PR 更新 baseline.json

10.10 測試分層在 Pipeline 的選擇

層級內容工具是否進入 CI
單元 (Unit)方法/函式驗證JUnit必須
整合 (Integration)服務協同JUnit + Testcontainers必須
輕量性能 (Smoke Perf)低併發/短時間JMeter 非 GUI必須
回歸性能 (Baseline)中等併發/固定時間JMeter每日/發版前
壓力 / 容量 / Soak高併發/長時間JMeter 分散式手動/排程

10.11 常見整合問題與排除

問題徵象可能原因解法
Pipeline 卡住無輸出JMeter 未在 PATH加入安裝步驟
報表空白HTML 缺統計JTL 未寫入 / 權限檢查磁碟 & 日誌
指標飆高與本地差異大CI 機器資源不足降 threads 或升級 runner
不可重複每次結果差異大暖機/資料汙染分離暖機 / 資料隔離
無法判斷退化沒有 baselineBaseline 缺失建立初始基準流程

10.12 小結

你現在應能:

  • 撰寫標準化非 GUI 執行腳本並於 CI 引用
  • 以 Exit Code 控制 Pipeline 成敗與 Warn 分級
  • 比較 Baseline 與當前指標並做審核更新
  • 管理多環境組態與安全注入敏感資訊
  • 規劃報表留存與層級化性能測試策略

下一章(第 11 章)將以電商 API 為例示範端到端腳本設計與 Correlation、比例流量與聚合事務分析。

11. API 實戰案例

案例背景:模擬電商平台「登入 → 瀏覽商品 → 搜尋 → 加入購物車 → 下單 → 查詢訂單狀態」之 6 個核心 API,並混入推薦查詢。目標:500 併發下 P95 < 1200ms,Error% < 1.5%。

11.1 場景拆解與使用者行為模型

子場景比例說明交易構成
瀏覽流量50%登入後多次商品查看login → listProducts → viewDetail(x2)
搜尋流量20%關鍵字查詢login → search?q=keyword
下單流量20%購物流程login → listProducts → addCart → checkout → orderStatus
推薦查詢10%取得個人化推薦login → recommendations

使用 Throughput Controller(百分比模式)或 Switch Controller(隨機加權)實現比例。

11.2 測試計畫結構範例

Test Plan
  + Thread Group (500 users, Ramp-up 300s)
    + CSV Data Set (users.csv)
    + HTTP Header Manager (Auth / JSON)
    + Module Controller (Login Fragment)
    + Throughput Controller (50%) -> Module: Browse Flow
    + Throughput Controller (20%) -> Module: Search Flow
    + Throughput Controller (20%) -> Module: Order Flow
    + Throughput Controller (10%) -> Module: Recommend Flow
    + Post-Processor Extractors
    + Assertions (SLA + 功能)
    + JS223 Listener (聚合錯誤 / SLA)
  + Test Fragment: Login Fragment
  + Test Fragment: Browse Flow
  + Test Fragment: Search Flow
  + Test Fragment: Order Flow
  + Test Fragment: Recommend Flow

11.3 Correlation 與資料流

抽取項來源 APIExtractor命名用途
token/auth/loginJSON Extractor $.tokenauth_token後續授權 Header
productId/products/listJSON Extractor $.items[0].idprod_id查看/下單
recId/recommendationsJSON Extractor $.recs[0].idrec_id推薦曝光 (可選)
orderId/order/checkoutJSON Extractor $.order.idorder_id訂單狀態查詢

命名規則仍沿用第 5 章:resp_ (回應派生)、ext_ (Extractor)、此處以語意清晰為主。

11.4 測試資料策略

類別來源策略注意
使用者帳號users.csv每 thread 獨立行避免同帳號 session 互斥
關鍵字keywords.csv循環或 weighted熱門詞 vs 冷門詞比例
商品資料API 即時取得動態抽取需處理空清單 fallback
訂單資料執行期產生不回寫 CSV以變數記錄供後續查詢

重點:資料池需足夠支援最大迴圈次數;若 users.csv 少於 threads 則需允許重複並註記風險。

11.5 控制器設計與比例實現

採 Throughput Controller(百分比模式)重播一次迴圈中各行為比例。若需使用「長時間持續比例」且避免單迴圈偏差,可考慮:

  1. 設定 Thread Group 為循環 -1(Forever)+ Duration;
  2. 對高頻場景加入 Timer 平衡節奏;
  3. 或改用 Switch Controller + ${__Random(1,100)} 門檻分流。

11.6 SLA 與 Assertions 範例

API功能 AssertionSLA Assertion備註
/auth/login狀態碼=200 且 JSON token 存在P95 < 500ms失敗直接中斷後續
/products/list狀態碼=200 且 items 長度>0P95 < 800ms
/order/checkout狀態碼=200 且 status='CREATED'P95 < 1500ms觀察尾延遲

JSR223 Assertion(動態 SLA 簡例):

def api = SampleResult.getSampleLabel()
def p95Limit = props.get("sla.p95.default","1200").toInteger()
if(api.contains('checkout')) p95Limit = props.get("sla.p95.checkout","1500").toInteger()
// 實際 P95 需在報表後計算;此處示例針對單請求時間的即時閾值
if(SampleResult.getTime() > p95Limit*2) { AssertionResult.setFailure(true); AssertionResult.setFailureMessage("HARD_SLA_X2:"+SampleResult.getTime()) }

單次請求無法直接判斷 P95,只能做硬性上界(例如 2 倍 SLA)。真正 P95 判讀於第 8 章流程後處理。

11.7 交易 (Transaction) 分析

將購物流程包成 Transaction Controller (ORDER_FLOW)

事務段內容觀測潛在瓶頸
LOGIN/auth/login認證延遲加密/DB 查詢
LIST/products/list商品列表快取/DB I/O
ADD_CART/cart/add寫入操作Session / DB 寫鎖
CHECKOUT/order/checkout生成訂單支付/庫存鎖定
STATUS/order/status?id=訂單查詢DB 索引

若 ORDER_FLOW P95 過高,需細分哪個子段落佔比最大(可另將子請求做單獨 Transaction Controller)。

11.8 失敗恢復與重試策略

狀況策略風險
登入 401單次重試(重新取得 token)過多重試掩蓋真實錯誤
下單 5xx不重試(記錄 FUNC_ERROR)真實失敗保留
商品空列表換預設商品 ID 或跳過流程影響比例統計

實作:在流程前以 If Controller 判斷 auth_token 是否存在,否則呼叫 Login Fragment。

11.9 定時器 (Timer) 與節奏 (Pacing)

避免過度壓縮請求造成非真實行為:

Timer用途設定建議
Uniform Random Timer模擬人為停頓300~800ms 查看商品
Constant Timer固定思考時間搜尋前 200ms
Throughput Shaping Timer (外掛)精準 RPS 控制需要外掛安裝

11.10 報表截取與指標彙整模板

執行完成後建立 order-flow-analysis.md

Scenario: ORDER_FLOW  併發=500  Duration=10m
ORDER_FLOW: Avg 980 / P95 1580 / Error 1.1%
  LOGIN      Avg 300 / P95 520
  LIST       Avg 260 / P95 480
  ADD_CART   Avg 180 / P95 400
  CHECKOUT   Avg 620 / P95 1100 (瓶頸)
  STATUS     Avg 140 / P95 300
建議:檢視 CHECKOUT 涉及之扣庫存 SQL / 支付服務延遲。

11.11 常見錯誤與排查清單(本案例)

現象可能原因排查步驟修正
大量 401token 過期/未帶 Header檢查 Header Manager加條件式重新登入
下單高錯誤率庫存鎖/支付第三方慢後端 log / APM增加快取或降併發
推薦 API 偶發 5xx外部推薦服務不穩分源統計circuit breaker 策略
ORDER_FLOW P95 飆升單段 CHECKOUT 慢分段指標DB 慢查詢 / 外部 API

11.12 小結

你現在應能:

  • 設計多比例複合行為的 API 測試場景
  • 實作關鍵值 Correlation 與資料池管理
  • 以 Transaction Controller 分析端到端耗時構成
  • 動態處理登入失效與基礎重試策略
  • 產出針對單一業務流程的瓶頸分析摘要

下一章(第 12 章)將聚焦 Web / 前端資源載入與 API 壓測差異、靜態資源與快取策略評估(骨架待擴充)。

12. Web / 前端資源載入

本章說明為何 JMeter 不等於「瀏覽器真實行為」,以及如何針對前端資源與 API 分離測試、評估快取/壓縮策略與靜態資源最佳化影響。

12.1 瀏覽器 vs JMeter 差異

面向瀏覽器JMeter影響
解析/渲染解析 HTML / CSS / JS / Layout / Paint不解析 DOM缺少前端計算成本
並行請求受瀏覽器連線限制 (HTTP/1.1)可大量併發無限制造成不真實資源競爭
Cache 行為瀏覽器遵守 Cache-Control預設無需模擬或忽略
JS 執行真實執行不執行無法測 TTI/FID
資源優先序會有優先級/預取排程行為不同

結論:JMeter 適合測後端 API / 靜態資源傳輸能力,不適合衡量 FP/LCP/CLS 等體驗指標,需配合 Lighthouse 或 RUM。

12.2 靜態資源測試策略

目的:確保 CDN / 靜態伺服器在併發下載下的吞吐延遲。

方式:

  1. 建立資源 URL 清單(JS/CSS/IMG 大小 > 0.5MB 或關鍵資源)。
  2. 使用 HTTP Request + 循環控制器下載資源。
  3. 可設定 Constant Throughput Timer 模擬每秒請求速率。
  4. 觀察 Bytes/sec、P95 latency、Error%(連線重設)。

12.3 Cache 與條件式請求模擬

情境Header期望驗證
首次下載無 If-None-Match200 + 資源內容回應大小 > 0
命中快取If-None-Match + ETag304 無內容回應大小=0
過期If-Modified-Since 與過期時間200 重傳新 ETag 變化

實作:在 JMeter 加 Header Manager 手動加上 If-None-MatchIf-Modified-Since 模擬瀏覽器重訪。

12.4 GZIP / Brotli 壓縮觀察

指標有壓縮無壓縮差異
下載大小 (KB)120480-75%
首包時間 TTFB (ms)9085接近
解壓 CPU 成本客戶端客戶端不測於 JMeter

結論:JMeter 只能看到傳輸層大小差異,不評估前端解壓渲染開銷。

12.5 SPA (Single Page App) API 測試

SPA 內部 API 多為 JSON 資料交換 → 使用第 11 章策略:聚合典型行為 + Token / Session 抽取。

避免:模擬下載所有 chunks/js split 檔案(因 JMeter 無執行 JS 意義不大)。

建議:針對 API 回應時間 + 功能完整性(關鍵欄位)即可。

12.6 下載資源組合測試範例

Thread Group (100 VU)
  + CSV: resources.csv (url,size)
  + HTTP Request (GET ${url})
  + Response Assertion (Size >= ${size})
  + Constant Throughput Timer (Target 300 req/min)

12.7 資源異常與退化判斷

現象指標可能原因行動
大量 404Error%發佈/同步失敗檢查 CDN 版本
延遲升高 + Bytes 小網路節點阻塞檢查網路路徑
304 命中率低Cache Miss%Header 設定錯誤檢視 Cache-Control
體積意外增長bytes diff打包未壓縮檢查 build pipeline

12.8 與前端效能工具協同

面向工具補足
首次渲染 (FCP/LCP)Lighthouse真實瀏覽器指標
使用者互動RUM (BoQ, Perfume.js)實際裝置分佈
後端 APIJMeter大量併發 / 長時間
整體追蹤APM + Tracing端到端耗時拆解

12.9 報表與度量聚合

蒐集:資源平均下載時間、Bytes/sec、304 比例、Error%。可輸出 static-metrics.json

{ "bytesTotal": 58200000, "avgLatency": 240, "p95Latency": 420, "cacheHit304Pct": 62.5 }

12.10 小結

你現在應能:

  • 理解 JMeter 在前端領域的適用邊界
  • 模擬靜態資源下載與 Cache 行為差異
  • 評估壓縮策略對傳輸的影響(非渲染)
  • 區分 API vs 靜態資源測試策略
  • 與 Lighthouse / RUM / APM 協同建立完整觀測

下一章(第 13 章)將聚焦資料庫與外部依賴模擬策略。

13. 資料庫 / 第三方整合

本章聚焦以 JMeter 測試 DB 層(讀/寫查詢)與外部服務(支付、佇列、第三方 API)模擬策略,並討論如何避免測試造成資料汙染。

13.1 JDBC Sampler 基礎

前置:/lib 放對應 JDBC Driver (e.g. mysql-connector-j.jar)。

配置:JDBC Connection Configuration → 設定 URL / 驗證 / Max Connections。

13.2 連線池 (Connection Pool) 考量

設定影響建議
Max Connections併發上限與系統 thread 模型對齊
Prepared Statements重複查詢效率開啟快取
Auto-commit寫入成本可批次則關閉後手動 commit
Transaction Isolation鎖行為測寫入需標明

13.3 查詢分類與指標

類型說明指標優化方向
單行查詢主鍵 / 唯一索引Avg/P95確認索引命中
範圍查詢時間/分頁P95/P99索引選擇 / 覆蓋索引
聚合查詢SUM/COUNT/GroupP95/CPU維度預聚合
寫入交易INSERT/UPDATEError%/延遲批次寫入 / 隔離級調整

13.4 慢查詢模擬與觀測

策略:

  1. 設置查詢參數觸發非最佳化路徑(如無索引欄位)。
  2. 使用不同資料規模(小/中/大表)對比延遲曲線。
  3. 觀測 DB 慢查詢日誌 / EXPLAIN 計畫差異。

13.5 測試資料與回滾策略

類型問題解法
寫入累積膨脹重複測試導致表變大定期清理 / 建沙盒 schema
主鍵衝突CSV 重複使用序列/時間戳/UUID
交易未提交引發鎖顯式 commit / rollback
不可逆操作真實扣庫存用模擬標記欄位而非真扣

13.6 外部依賴模擬 (Stub / Mock)

依賴風險模擬方式工具
支付服務有金流風險Mock API 回傳固定結果WireMock / MockServer
推薦服務不穩定延遲延遲注入 / 隨機錯誤自建簡易 HTTP Mock
訊息佇列真實消費副作用虛擬 Endpoint / 本地 embedded brokerActiveMQ embedded
第三方授權Token 有效期預生成假 Token自訂簡易簽發服務

13.7 佇列 / 非同步行為測試

JMeter 不適合等待長尾非同步處理結果。策略:

  1. 發送消息後輪詢狀態(加上最大重試與超時)。
  2. 或只測入口吞吐(忽略下游消費)。

13.8 整合指標交叉分析

症狀DB 指標App 指標可能原因
查詢延遲線性上升QPS 穩定 / RT 升CPU 上升記憶體快取失效
間歇尖峰Buffer Pool MissGC Minor 對齊資料熱換出
寫入失敗Deadlock 計數Error log交易鎖競爭

13.9 與後端團隊協同流程

sequenceDiagram participant T as Tester participant D as DBA participant A as App Dev T->>T: 設計查詢分類清單 T->>D: 確認索引/資料規模 T->>A: 提供延遲/錯誤樣本 D-->>T: 回傳 EXPLAIN / 慢查詢分析 A-->>T: 提供應用層 log/Thread dump T->>T: 更新報告與建議

13.10 小結

你現在應能:

  • 使用 JDBC Sampler 測試 DB 查詢並理解連線池要素
  • 分類查詢類型並對應指標與優化方向
  • 設計慢查詢模擬並收集 EXPLAIN / 慢查詢 log
  • 採用資料回滾與模擬策略避免汙染與副作用
  • 區分外部依賴模擬層級並與後端/DBA 協同分析

接下來將細化認證與進階學習章節骨架。


14. 認證考試重點

本章彙整常見 JMeter / 效能測試認證或內部能力評估的出題主題映射、術語、陷阱與考前節奏建議,協助集中複習。

14.1 主題分佈映射

主題區塊估計占比本教材對應備註
測試計畫/元件15%4 / 6Thread、Controller 行為
參數化/Correlation15%5 / 11抽取策略與優先序
控制流/比例場景10%6 / 11Throughput / Switch
Assertions/SLA10%7 / 10 / 11動態門檻策略
報表/百分位10%8 / 10分布解讀 / Diff
效能方法論15%9升壓 / 暖機 / 回歸
CI/CD 自動化5%10Exit Code / Baseline
API 實戰結構10%11Transaction / 比例設計
前端/靜態資源5%12Cache / 適用邊界
DB / 外部依賴5%13慢查詢 / 模擬

14.2 必背術語速覽

術語精準定義高頻誤解快速記憶關鍵句
P9595% 請求延遲不超過的值等於平均分布位置非平均
Throughput單位時間成功完成請求數等於 ThreadsThreads 直接等於 RPS
Correlation抽取動態值再重放只做 Regex所有動態都需抽取
Baseline參考性能指標集合不可更新條件變動需重建
Warm-up剃除不穩定初段可忽略提升穩定度基礎
Error%錯誤回應比例只看 500包含 Assertion 失敗

14.3 高頻陷阱類型

類型陷阱描述正確認知
指標混淆P95 = 平均百分位為排序定位
控制器語意Throughput Controller 百分比=精準 RPS是取樣比例非直接 RPS
變數作用域CSV vs UDV 覆寫作用域優先序需記憶
升壓策略一次性瞬間拉滿應階梯或線性漸進
報表讀法Error% 與 Latency 無關需交叉觀測分布與錯誤類型

14.4 模擬測驗檢查清單

項目確認點
指標定義Avg / Median / P95 / P99
百分位判讀長尾影響與離群值
腳本結構Login/業務拆分 / 共用模組
參數化CSV 共享模式 & Correlation
Assertions充足且聚合
報表輸出HTML Dashboard + 原始 JTL
基準線對比是否有上次結果

14.5 考前 24 小時節奏

時段任務目標
0–2h章節索引掃描建立即時記憶回路
2–4h指標 + 百分位專注強化數據語意
4–6h腳本結構與控制器練習避免語意混淆
6–7h報表 Diff 練習熟悉趨勢判斷
7–8hFlash Cards術語強化

14.6 Flash Cards(示例)

P95 vs P99 → 代表長尾敏感度不同
Throughput 變動但 Threads 不變 → 後端延遲或資源瓶頸
Error% 上升但 2xx 仍多 → 可能 Assertion 失敗混入
Warm-up 為何必要 → 移除環境與 JVM 初期不穩定
Baseline 何時重建 → 架構/設定/版本重大改變

14.7 小結

本章提供認證聚焦與術語集,可與第 8 / 9 / 10 / 11 章實戰練習交叉加深記憶。

15. 題庫與解析框架

建立可維護題庫格式 + 解析結構,支援自動統計與品質管控。

15.1 題型分類維度

維度類別用途
知識深度記憶 / 理解 / 應用 / 分析區分學習層級
技術面變數 / 控制器 / Assertions / 報表精準標籤檢索
方法論升壓 / 暖機 / Baseline / 比例概念交叉覆蓋
風險型延遲 / 吞吐 / 穩定 / 資料汙染場景導向

15.2 題目 YAML 標準

- id: Q011
  type: scenario
  tags: [controller, throughput, percent]
  question: 某腳本使用 Throughput Controller 50% + Switch Controller,報表顯示實際占比 35%,原因可能為何?
  options:
    - 配置生效,屬正常波動
    - 外層還有其它請求影響比例母數
    - 百分比會自動調整為實際 RPS
    - JMeter 版本 bug
  answer: 1
  rationale: 分母包含其它取樣導致實際比例低於設定值

15.3 解析四段式框架

段落目標提示
題幹重述確認焦點不帶主觀推論
核心概念精準定義必要術語引用
選項剖析排除干擾指出陷阱語言
實務延伸與場景連結加深記憶

15.4 題庫品質控制構想

模組功能風險控制
結構解析YAML schema 驗證避免欄位缺漏
Tag Lint標籤拼寫/未使用回報防標籤碎片化
統計報告題量/標籤占比辨識覆蓋盲區
重複檢測題幹語義相似度移除冗餘

15.5 題庫版本流程

flowchart LR A[新增題案] --> B[標籤審核] B --> C[技術複核] C --> D[主題庫合併] D --> E[統計覆蓋報告] E --> F{缺口?} F -- 是 --> A F -- 否 --> G[標記版本]

15.6 練習集建議配置

類型題量重點
概念單選30術語 / 指標
場景判斷15控制器 / 結構
報表解析10百分位 / Diff
腳本片段10Groovy / 變數
綜合案例5策略設計

15.7 小結

題庫框架 = 結構化 YAML + 解析四段式 + 覆蓋統計,可納入 CI 做品質門檻。

16. 進階學習與延伸

由工具層面進入觀測、方法論、治理與資料化性能優化路徑。

16.1 進階主題地圖

層級主題產出能力
工具延伸Gatling / k6 / Locust負載模型差異對比
追蹤OpenTelemetry / 分散追蹤服務瀑布定位瓶頸
自動化Baseline Diff / 漂移偵測退化早期預警
數據分析分布 / Outlier / Histogram長尾與異常解析
治理SLO / Error Budget性能成為發版條件

16.2 性能成熟度模型

階段現況缺口升級措施
初始手動執行 / 無基準不可重現腳本版本控管
建立有報表 / 單次對比缺趨勢保存歷史 + Diff
自動CI 觸發 + 門檻門檻僵化動態百分位策略
預測趨勢與預警根因慢Trace 關聯
治理性能 KPI 化成本未知成本指標導入

16.3 延遲與異常分析起步

問題方法期待輸出
長尾HDR HistogramTail 區塊定位
間歇尖峰Sliding Window DiffSpike 樣本切片
漸進退化Regression 線性擬合退化趨勢斜率

16.4 Trace 整合實務

在 HTTP Header 注入 X-Perf-Trace-Id=${__UUID()};APM / Tracing 平臺以此聚合 Transaction → 對照 Thread dump / DB 慢查詢縮小瓶頸面。

16.5 持續優化季度節奏

月份活動產出
M1基準盤點服務指標基線
M2聚焦改進P95 改善清單
M3回歸 / 指標回顧趨勢報告 / 新 SLO

16.6 推薦延伸資源

類型資源強化面
書籍Systems Performance作業系統性能基礎
書籍Release It!穩定性/彈性模式
規範OpenTelemetry可觀測語意
工具k6 / Gatling模型差異與腳本風格
社群CNCF / perf 工具組案例交流

16.7 小結

進階能力 = 工具多樣化 + 觀測鏈整合 + 自動化退化偵測 + 治理節奏,使性能測試從一次性活動轉為持續資產。


附錄 A. 最終測試計畫 Checklist

類別檢查項完成(Y/N)說明 / 備註
結構Test Plan 是否僅一層 Thread Group (必要時多組獨立場景)避免過深巢狀
結構公用步驟是否抽成 Test Fragment + Module/IncludeLogin / Health Check
變數Base URL / Token / 環境差異是否無硬編都用 ${__P()} 或 UDV
變數CSV Data Set 是否設定正確共享模式確認無資料競爭
變數Correlation 抽取變數命名統一 (resp_/ext_)便於搜尋排錯
控制Throughput / Switch 百分比總和合理實測統計接近預期
控制While 具最大次數防護避免無窮迴圈
控制Transaction Controller 僅包端到端關鍵事務無過度嵌套
Assertion狀態碼、關鍵欄位、錯誤字串黑名單已覆蓋失敗訊息一致
Assertion使用 JSON Assertion / JSR223 聚合錯誤避免太多零碎 Assertion
SLA有定義 P95 / Error% 門檻並記錄基準值baseline.properties 已更新
非 GUI有提供啟動腳本 (.bat/.sh) 與輸出路徑命名規則reports/<date>-<scenario>
非 GUI使用 -q 管理多環境屬性dev/stage/prod
報表HTML Dashboard 產出無錯誤 (資源完整)初次執行確認
報表聚合報表中無大量 0 Byte / 空回應否則排查超時/錯路徑
資源測試主機 CPU / Memory / 網路未飽和監控或 top / sar
日誌jmeter.log 無大量重複 WARNING/ERROR有則先清理噪音
清潔未使用的 Sampler/Listener 已移除或註記減少干擾
整合CI Pipeline 退出碼策略定義門檻 vs 失敗條件

附錄 B. 常見錯誤 / 緊急排障對照

症狀可能原因優先檢查快速動作
大量 0ms / 0 bytes目標 Server 未連通Host/Port、DNSping / curl 測通
Error% 突然飆升新版本缺陷 / 依賴掛掉狀態碼分類先快照日誌
Throughput 不穩定測試端 CPU 飽和 / GC主機監控降 Threads / 提升硬體
回應延遲階梯上升連線池耗盡 / 排隊Server thread/DB 連線擴增池或降併發
P95 波動大暖機不足 / 瞬時抖動前 1-2 分鐘資料排除暖機區段
登入失敗連鎖Token 過期未刷新Login 流程加重新登入機制
CSV 重複或混亂共享模式不當CSV 設定分檔或 thread 模式
GC 長停頓Heap 配置不足JVM GC log增加記憶體 / 調整物件產生
Assertion 過慢過多 Regex / 巨大字串斷言配置精簡或改 JSONPath

附錄 C. 範例報告模板(摘要草稿)

專案:<ProjectName>   測試日期:2025-09-17  版本:vX.Y
場景描述:100 Threads,Ramp-up 2m,循環 10,模擬 70% 瀏覽 / 20% 搜尋 / 10% 下單

環境:
  - 測試端:8 vCPU / 16GB RAM
  - 目標環境:staging-cluster-3 nodes
  - Java 版本:Temurin 17

指標摘要:
  - 總請求數:120,000
  - Throughput:950 req/s
  - Avg RT:420 ms  | P95:780 ms | P99:1100 ms
  - Error%:0.85% (功能 0.4% / SLA 0.3% / 環境 0.15%)
  - 最大併發(Active Threads 曲線):平穩達標

關鍵事務 (Transaction) 指標:
  - ORDER_FLOW:Avg 980 ms / P95 1600 ms / Error 1.2%
  - LOGIN:Avg 300 ms / P95 520 ms / Error 0.2%

資源觀察:
  - App CPU 最高 72%,無明顯飽和
  - DB 平均連線使用 65%(峰值 85%)
  - GC 停頓最大 150 ms,無 Full GC

發現與建議:
  1. ORDER_FLOW P95 接近 1.6s(門檻 1.5s)需檢視 DB 查詢計畫
  2. 少量 502 來自第 2 節點,建議檢視反向代理健康檢查設定
  3. 建議對登入 token 增加快取,減少重複驗證耗時

後續行動:<Owner / Due Date>

附錄 D. 建議檔案 / 目錄標準化命名

路徑說明範例
perf-test/scripts/主 JMX 與模組化片段ecommerce-main.jmx
perf-test/env/環境屬性檔dev.properties / stage.properties
perf-test/data/測試資料 CSVusers.csv / products.csv
perf-test/reports/HTML Report 與 jtl2025-09-17-login-smoke/
perf-test/bin/啟動腳本run-smoke.bat / run-load.sh
perf-test/lib/外掛 / 驅動mysql-connector.jar

附錄 E. 後續可延伸主題(進階)

  • 分散式執行(Remote / Distributed / Kubernetes)
  • 與 APM (e.g., Prometheus + Grafana) 對接
  • 壓測資料遮罩與脫敏機制
  • 混合協定(HTTP + Kafka + DB)端到端壓測
  • Performance Budget 與自動化回歸趨勢線