第一章. 性能测试通识与环境搭建

第一章. 性能测试通识与环境搭建

摘要:本章作为全系列的基石,我们将首先厘清性能测试的核心指标(TPS、RT),接着快速搭建一个基于 Spring Boot 的待测应用,最后完成 JMeter 的安装与基础环境配置,为后续的压测实战做好准备。

本章学习路径

我们将按照以下步骤构建性能测试的实验环境:

  • 1.1 核心概念扫盲
    • 1.1.1 性能测试的本质与目的
    • 1.1.2 关键指标详解:$TPS$ 与 $RT$
  • 1.2 搭建待测靶场(Spring Boot)
    • 1.2.1 使用 IDEA 快速初始化项目
    • 1.2.2 编写模拟业务延迟的测试接口
    • 1.2.3 验证服务可用性
  • 1.3 JMeter 环境部署
    • 1.3.1 JDK 环境检查(前置条件)
    • 1.3.2 JMeter 下载与目录结构解析
    • 1.3.3 关键配置修改(中文支持/编码格式)

1.1. 核心概念扫盲:什么是 “抗揍” 的代码

在正式动手之前,我们必须先统一语言。很多开发者认为 “程序没报错” 就是开发完成了,但在高并发场景下,功能正常的代码可能会因为资源耗尽而导致服务雪崩。

1.1.1. 性能测试的定义

性能测试(Performance Testing)是通过自动化的工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。

对于 Spring Boot 开发者而言,它的核心价值在于:

  1. 识别瓶颈:找到系统的短板(是 CPU 算不过来,还是数据库连接不够用)。
  2. 规划容量:明确系统最大能支撑多少用户同时访问。
  3. 验证稳定性:确保系统在长时间高负载下不会内存溢出(OOM)。

1.1.2. 黄金指标:$TPS$ 与 $RT$

在后续的 JMeter 报告中,我们最关注两个指标,它们存在着一种制衡关系:

  1. 响应时间 ($RT$ - Response Time)
  • 定义:从客户端发起请求到接收到完整响应所消耗的时间。
    * 体感:用户觉得 “卡不卡”。
    * 标准:通常互联网应用要求核心接口 $RT < 200ms$。
  1. 每秒事务数 ($TPS$ - Transactions Per Second)
  • 定义:系统每秒钟能够处理的业务请求数量。
    * 体感:系统能 “抗多少人”。
    * 关系:在理想情况下,$TPS \approx \frac{并发数}{RT}$。

注意:$TPS$ 和 $RT$ 往往是反比关系。当并发过高导致系统拥堵时,$RT$ 会急剧上升,从而导致 $TPS$ 下降。寻找这两者的 “平衡点” 就是性能调优的目标。


1.2. 搭建待测靶场:Spring Boot 测试项目

在上一节中,我们明确了性能测试的目标。为了让后续的 JMeter 学习有真实的 “攻击目标”,我们需要先构建一个标准的 Spring Boot 应用。为了模拟真实的业务场景,我们不能只写一个简单的 Hello World,而需要模拟出一定的 “耗时”。

1.2.1. 项目初始化

我们将使用 IntelliJ IDEA 快速构建项目。

操作步骤

  1. 打开 IDEA,点击 New Project
  2. 选择 Spring Initializr
  3. Name: jmeter-demo
  4. JDK: 推荐选择 21(2025 年主流 LTS 版本),我们在后续会测试虚拟线程
  5. Java: 选择对应版本。
  6. Packaging: Jar。
  7. 点击 Next,在依赖选择中勾选:
    • Web -> Spring Web (提供 REST 接口支持)。
    • Lombok (简化代码,可选)。

image-20251119092046741

1.2.2. 编写模拟业务接口

我们需要编写一个 Controller,并模拟一定的业务处理时间(例如查询数据库耗时)。

文件路径

1
2
3
4
src/main/java/com/demo/jmeterdemo/
├── JmeterDemoApplication.java
└── controller/
└── TestController.java # 我们将创建这个文件

代码实现

我们首先定义一个简单的 REST 接口,使用 Thread.sleep 来模拟业务逻辑的耗时。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.demo.jmeterdemo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

// 1. 定义 RestController
@RestController
@RequestMapping("/api/test")
public class TestController {

/**
* 模拟一个简单的业务查询接口
* 场景:用户查询商品详情,预计耗时 50ms - 100ms
*/
@GetMapping("/hello")
public Map<String, Object> hello() throws InterruptedException {
// 2. 模拟业务处理时间(随机延迟)
// 在真实压测中,接口一定是有耗时的,0ms 的接口没有压测意义
int sleepTime = ThreadLocalRandom.current().nextInt(50, 100);
Thread.sleep(sleepTime);

// 3. 封装返回结果
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "success");
result.put("data", "Processing time: " + sleepTime + "ms");
result.put("timestamp", System.currentTimeMillis());

return result;
}
}

代码解析

  • ThreadLocalRandom:在高并发环境下,它的性能优于 Random 类,用于生成随机数。
  • Thread.sleep:我们强制让线程休眠 50-100 毫秒。这是为了模拟真实项目中数据库查询或远程调用所需的 IO 等待时间。如果接口响应太快(0ms),JMeter 可能瞬间把 CPU 打满,无法观察到真实的并发排队现象。

1.2.3. 启动与验证

  1. 运行 JmeterDemoApplication.java 中的 main 方法。
  2. 打开浏览器访问:http://localhost:8080/api/test/hello
  3. 如果看到类似 {"code":200,"data":"Processing time: 76ms" ...} 的 JSON 返回,说明靶场搭建成功。

1.3. JMeter 环境部署

靶场已经就位,现在我们需要部署压测工具 JMeter。JMeter 是基于 Java 开发的,因此必须依赖 JDK 环境。

1.3.1. 前置检查:JDK

打开终端(Command Prompt 或 Terminal),输入以下命令:

1
java -version
  • 成功:输出 java version "17.0.x" 或更高版本。
  • 失败:如果提示 'java' is not recognized(‘java’ 不是内部或外部命令),请先安装 JDK 并配置 JAVA_HOME 环境变量。这是 Java 开发的基本功,不再赘述。

1.3.2. 下载与安装

Apache JMeter 是免安装的绿色软件。

  1. 下载:访问 Apache JMeter 官网
  2. 选择版本:找到 Binaries(二进制版)区域。
    • Windows 用户下载 .zip 文件。
    • Mac/Linux 用户下载 .tgz 文件。
    • 注意:不要下载 Source(源码版),那是给开发者看源码用的。
  3. 解压:将压缩包解压到一个 没有中文、没有空格 的路径下(例如 D:\tools\apache-jmeter-5.6.3/usr/local/jmeter)。

目录结构说明

  • bin/:存放启动脚本(jmeter.bat, jmeter.sh)和配置文件(jmeter.properties)。
  • lib/:存放 JMeter 的核心 Jar 包和第三方插件。
  • docs/:官方文档。

1.3.3. 基础配置优化

默认的 JMeter 配置是英文界面且编码可能存在问题,我们需要在启动前做一次 “手术”。

文件路径[JMeter安装目录]/bin/jmeter.properties

使用文本编辑器(如 Notepad++ 或 VS Code)打开该文件,完成以下修改:

image-20251119092512755

1. 界面语言设置为中文
JMeter 原生支持中文,修改配置可永久生效。

1
2
# 搜索 language,去掉前面的 # 号
language=zh_CN

2. 强制使用 UTF-8 编码
这是为了防止压测过程中响应数据出现中文乱码。

1
2
# 搜索 sampleresult.default.encoding
sampleresult.default.encoding=UTF-8

3. 启动验证

  • Windows:双击 bin/jmeter.bat
  • Mac/Linux:在终端执行 sh bin/jmeter.sh

常见错误:启动时如果出现终端一闪而过,通常是因为 JAVA_HOME 环境变量未配置正确。

如果成功看到了 JMeter 的图形化界面(GUI),并且菜单栏是中文的,恭喜你,所有的准备工作已经就绪。


1.4. 本章小结

在本章中,我们完成了从理论认知到环境搭建的全过程。现在,你的电脑上同时运行着一个 “脆弱” 的 Spring Boot 应用和一个 “强大” 的压测工具。

核心要点

  1. TPS 与 RT:$TPS$ 是吞吐量,$RT$ 是延迟,两者通常呈反比。
  2. 测试靶场:压测必须基于具有真实业务耗时(Sleep)的接口,0ms 的接口没有测试价值。
  3. 环境隔离:JMeter 安装路径严禁包含中文或空格,否则会导致未知的 Java 类加载错误。

下一步计划:我们的 “枪”(JMeter)和 “靶子”(Spring Boot)都准备好了。在下一章,我们将编写第一个 JMeter 测试脚本,真正地扣动扳机,看看我们的 Spring Boot 应用在 100 个并发线程下表现如何。