➜ Old React website
Chung Cheuk Hang MichaelJava Web Developer
寫一個 Maven Java shared library自建 Nexus Maven repo

JMeter performance testing

Table of contents

1 JMeter 簡介

Apache JMeter 係一款專門做 API performance testing 既工具,佢可以用 multithreading 去模擬多個 users(或者 downstream clients)同時 request 需要測試既 HTTP APIs,然後佢會紀錄低 HTTP response、throughput、耗時等等既數據。

1.1 下載 JMeter

2 動手做

我地會寫一個 Spring Boot web application,裡面會有以下既 HTTP APIs,我地既 JMeter script 都會根據相同既次序黎 loop HTTP API calls:
次序HTTP API作用JMeter 測試須知
1GET /api/uppercase/{value}{value} 變成大楷然後返回。用 User Parameters 既隨機數據作為 request input;用 BeanShell PostProcessor 將 response body save 低。
2GET /api/toJson/{value}{value} 放入一個 object 裡面然後返回。用 JSR223 PostProcessor 將 response body 既某個 JSON field save 低。
3GET /api/lowercase/{value}{value} 變成細楷然後返回。N/A

2.1 建立 Spring Boot web microservice

2.1.1 Maven dependencies

我地會加入 Spring Security 去令個 microservice 既 HTTP requests respond 得慢啲。
1<parent> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-parent</artifactId> 4 <version>3.3.4</version> 5</parent> 6 7<dependencies> 8 <dependency> 9 <groupId>org.springframework.boot</groupId> 10 <artifactId>spring-boot-starter-web</artifactId> 11 </dependency> 12 <dependency> 13 <groupId>org.springframework.boot</groupId> 14 <artifactId>spring-boot-starter-security</artifactId> 15 </dependency> 16</dependencies>

2.1.2 寫 Java code

SampleController.java
1@RestController 2@RequestMapping("/api") 3public class SampleController { 4 5 @GetMapping("/uppercase/{value}") 6 public String uppercase(@PathVariable(name = "value", required = true) String value) { 7 return value.toUpperCase(); 8 } 9 10 @GetMapping("/toJson/{value}") 11 public MyDto toJson(@PathVariable(name = "value", required = true) String value) { 12 return new MyDto(value, Arrays.asList(new MyDto2(3L, new BigDecimal("5.6")))); 13 } 14 15 @GetMapping("/lowercase/{value}") 16 public String lowercase(@PathVariable(name = "value", required = true) String value) { 17 return value.toLowerCase(); 18 } 19}

2.1.3 Application 配置

spring: security: user: name: mick password: foobar

2.2 建立 JMeter JMX 檔

我地會用 JMeter 既介面幫我地建立 JMX 檔,我地會將個 JMX 檔保存做 jmeter.jmx

2.2.1 新增 Thread Group

  1. Right-click Test Plan > Add > Threads (Users) > Thread Group。
  2. 將 Number of Threads (users) 改成 ${__P(threadCount, 500)}
  3. 將 Ramp-up period (seconds) 改成 0
  4. 將 Loop count 改成 ${__P(loopCount, 200)}

2.2.2 新增 HTTP Authorization Manager

因為我地有用到 Spring Security 去做 basic authentication,所以我地要加入 HTTP authorization manager:
  1. Right-click Thread Group > Add > Config Element > HTTP Authorization Manager。
  2. 撳下面「Add」。
  3. Username 輸入 mick
  4. Password 輸入 foobar

2.2.3 新增 User Parameters

我地可以用 user parameters 黎定義 variables。
  1. Right-click Thread Group > Add > Pre Processors > User Parameters。
  2. 啟用「Update Once Per Iteration」。
  3. 撳下面「Add Variable」。
  4. Name 輸入 myRandomVal
  5. User_1 輸入 ${__RandomString(10, abcdefghijklmnopqrstuvwxyz)}
註:
  • 我地應該用 user parameters 而唔係 user-defined variables。
    • 因為 user parameters 喺每個 iteration/loop 都會 reset;相反,user-defined variables 一直都會維持一樣既 values。

2.2.4 新增 HTTP Request

  1. 新增第 1 個 HTTP request。
    1. Right-click Thread Group > Add > Sampler > HTTP Request。
    2. 將 Name 改成 HTTP Request - /api/uppercase/{value}
    3. Protocol 輸入 http
    4. Server Name or IP 輸入 localhost
    5. Port Number 輸入 8080
    6. Path 輸入 /api/uppercase/${myRandomVal}
  2. 新增第 2 個 HTTP request。
    1. Right-click 岩岩整既 HTTP request > Duplicate。
    2. 將 Name 改成 HTTP Request - /api/toJson/{value}
    3. 將 Path 改成 /api/toJson/${myTempVal}
  3. 新增第 3 個 HTTP request。
    1. Right-click 岩岩整既 HTTP request > Duplicate。
    2. 將 Name 改成 HTTP Request - /api/lowercase/{value}
    3. 將 Path 改成 /api/lowercase/${myTempVal}

2.2.5 新增 BeanShell PostProcessor

  1. Right-click HTTP Request - /api/uppercase/{value} > Add > Post Processors > BeanShell PostProcessor。
  2. Script 輸入 vars.put("myTempVal", new String(data));

2.2.6 新增 JSR223 PostProcessor

  1. Right-click HTTP Request - /api/toJson/{value} > Add > Post Processors > JSR223 PostProcessor。
  2. Script 輸入 vars.put("myTempVal", prev.items[0].productName);

2.2.7 新增 View Results Tree

  1. Right-click Thread Group > Add > Listener > View Results Tree。

2.2.8 新增 Summary Report

  1. Right-click Thread Group > Add > Listener > Summary Report。

3 測試

我地配置左:
  • 500 個 users
  • 200 個 loops
  • 3 個 HTTP requests
總共就會發起 500 × 200 × 3 即係 300000 個 HTTP requests。

3.1 用介面執行

  1. 撳上面 menu bar 下一行既綠色「▶️」掣開始 performance testing。
  2. 等佢運行一陣。
  3. 檢視 Views Results Tree,我地會見到所有 HTTP responses 都係綠色,即係成功。
  4. 檢視 Summary Report,我地會見到「TOTAL」既 throughput。

3.2 用 command 執行

rmdir /s /q "output" mkdir "output" jmeter -n -t "jmeter.jmx" -l "./output/result.jtl" -e -o "./output/dashboard" -J threadCount=500 -J loopCount=200
執行完之後,JMeter 會生成:
  • HTML dashboard 檔案,我地可以用瀏覽器打開睇。
  • JTL 檔案,係包含所有 HTTP requests 既結果既 raw data,裡面係 CSV 格式。
註:
  • 根據以上結果,CLI 模式(又叫 non-GUI 模式)既 throughput 居然會低過 GUI 模式。
  • 不過,官方話我地係應該以 CLI 模式既結果為準。

4 參考資料