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

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

摘要:本章作为全系列的基石,我们将首先厘清性能测试的核心指标(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 个并发线程下表现如何。