JMeter压力测试实战:100并发压测模拟电商API的完整过程(附脚本与报告)

举报
yd_265411139 发表于 2026/10/23 14:33:52 2026/10/23
【摘要】 # JMeter压力测试实战:100并发压测模拟电商API的完整过程(附脚本与报告)> 【摘要】网上讲 JMeter 的文章很多,但真正从头到尾跑一遍的少。本文在一个干净的 Linux 环境里,从安装 JMeter、搭建被测服务、编写含参数化与断言的测试计划,到命令行压测出报告,完整走了一遍,900 个样本 0 错误。文中附完整脚本与压测数据,可照着复现。## 一、为什么要"温柔地"压测自己...

# JMeter压力测试实战:100并发压测模拟电商API的完整过程(附脚本与报告)

> 【摘要】网上讲 JMeter 的文章很多,但真正从头到尾跑一遍的少。本文在一个干净的 Linux 环境里,从安装 JMeter、搭建被测服务、编写含参数化与断言的测试计划,到命令行压测出报告,完整走了一遍,900 个样本 0 错误。文中附完整脚本与压测数据,可照着复现。

## 一、为什么要"温柔地"压测自己的服务

压力测试的目的不是把服务器打趴下,而是:

- **发现瓶颈**:找到系统的"最短木板"
- **验证容量**:知道系统能承受多少用户
- **建立基线**:为后续性能优化提供数据支持

本文实践的环境:

| 项目 | 版本/说明 |
|------|----------|
| 操作系统 | Huawei Cloud EulerOS 3.0 (aarch64) |
| Java | OpenJDK 17 |
| JMeter | Apache JMeter 5.6.3 |
| 被测服务 | Python 自建模拟电商 API |

## 二、第1步:安装 JMeter

JMeter 是纯 Java 应用,装好 Java 后解压即用:

```bash
# 先检查 Java 环境
java -version
# openjdk version "17" ...

# 下载 JMeter(国内推荐华为云镜像,速度快很多)
curl -L -o jmeter.tgz \
  https://mirrors.huaweicloud.com/apache/jmeter/binaries/apache-jmeter-5.6.3.tgz

# 解压并验证
tar -xzf jmeter.tgz
mv apache-jmeter-5.6.3 /opt/jmeter
/opt/jmeter/bin/jmeter --version
```

**踩坑提醒**:官方 dlcdn 源国内访问很慢甚至超时,换华为云镜像后 83MB 几秒下完。另外解压路径别带中文,否则配置文件读写可能出乱码问题。

## 三、第2步:搭建被测服务(模拟电商 API)

没有真实系统怎么练手?自己写一个。用 Python 标准库搭一个模拟电商 API,包含三个接口:

- `POST /api/login` —— 登录,返回 token
- `GET /api/product` —— 浏览商品列表
- `POST /api/order` —— 下单(需要 token 鉴权)

```python
# mock_ecommerce_api.py(节选,完整代码见文末说明)
import json, random, threading, time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

USERS = {
    "zhangsan123": ("zhangsan", 1001),
    "lisi456":     ("lisi", 1002),
    "wangwu789":   ("wangwu", 1003),
}
tokens = set()

class Handler(BaseHTTPRequestHandler):
    def do_POST(self):
        if self.path == "/api/login":
            # 模拟业务处理耗时 20~80ms
            time.sleep(random.uniform(0.02, 0.08))
            ...
            self._send(200, {"success": True,
                             "userId": user[0],
                             "access_token": token})
        elif self.path == "/api/order":
            # 模拟下单耗时 50~150ms,校验 token
            ...

class Server(ThreadingHTTPServer):
    daemon_threads = True

Server(("127.0.0.1", 8080), Handler).serve_forever()
```

接口里故意加了 `time.sleep()` 模拟真实业务耗时——压测一个秒回的服务是没有意义的。

启动并验证:

```bash
python3 mock_ecommerce_api.py &
curl -s -X POST http://127.0.0.1:8080/api/login \
  -H "Content-Type: application/json" \
  -d '{"username":"张三","password":"zhangsan123"}'
# {"success": true, "userId": "zhangsan", "access_token": "tk-zhangsan-67062"}
```

## 四、第3步:参数化数据——让每个虚拟用户都不一样

真实用户不会都用同一个账号。创建 `users.csv`:

```csv
username,password,productId
张三,zhangsan123,1001
李四,lisi456,1002
王五,wangwu789,1003
...(共300行)
```

在 JMeter 测试计划中添加 **CSV 数据文件设置**:

```
文件名:/path/to/users.csv
编码:UTF-8
变量名:username,password,productId
是否允许带引号:false
遇到文件结束再次循环:true
线程共享模式:全部线程
```

**注意**:中文数据一定要指定 UTF-8 编码,否则 POST 出去的中文用户名会变问号。

## 五、第4步:测试计划设计

测试计划的结构(对应 JMeter 的树形组件):

```
测试计划:双十一压力测试
└── 线程组:100个虚拟用户(Ramp-up 10秒,循环3次)
    ├── CSV数据文件设置:users.csv
    ├── 登录请求(POST /api/login)
    │   ├── HTTP信息头管理器:Content-Type: application/json
    │   ├── JSON提取器:$.access_token → 变量 token
    │   └── 响应断言:包含 "success": true
    ├── 浏览商品(GET /api/product)
    │   └── 响应断言:包含 "success": true
    ├── 下单请求(POST /api/order)
    │   ├── HTTP信息头管理器:Content-Type + Authorization: Bearer ${token}
    │   ├── 响应断言:包含 "success": true
    │   └── 持续时间断言:3000毫秒(超3秒即失败)
    ├── 高斯随机定时器:偏差200ms,固定延迟1000ms
    └── 聚合报告(监听器)
```

几个关键设计点:

**1. 关联提取**:登录拿到的 token 要传给下单请求。用 JSON 提取器配置 `$.access_token`,下游请求头里写 `Bearer ${token}`,就完成了接口串联。

**2. 断言**:光返回 200 不代表业务成功,加响应断言检查 `"success": true`;再加持续时间断言 3000ms,响应超 3 秒直接判失败——这是给服务器划的红线。

**3. 高斯随机定时器**:偏差 200ms + 固定延迟 1000ms,即每个请求前等待 1000±200ms。**没有思考时间的压测等于机器人 DDos,有思考时间的压测才像真人**。

**4. 循环渐进**:先 5 线程冒烟验证脚本,确认 0 错误后再上 100 线程,一上来就全量压测,脚本有错都不知道错在哪。

## 六、第5步:命令行压测与报告

正式压测别用 GUI(GUI 里的监听器很吃资源),用非 GUI 模式 + 自动生成 HTML 报告:

```bash
/opt/jmeter/bin/jmeter -n -t double11_test.jmx \
  -l result.jtl -e -o report
```

参数说明:`-n` 非图形模式,`-t` 指定测试计划,`-l` 结果文件,`-e` 压测结束后生成报告,`-o` 报告输出目录。

控制台实时输出:

```
summary +    84 in 00:00:05 =   17.3/s Avg:    54 ... Err: 0 (0.00%)
summary +   816 in 00:00:15 =   55.6/s Avg:    62 ... Err: 0 (0.00%)
summary =   900 in 00:00:20 =   46.1/s Avg:    62 Min: 11 Max: 177 Err: 0 (0.00%)
```

## 七、压测结果分析

| 请求名称 | 样本数 | 错误率 | 平均(ms) | 最小(ms) | 最大(ms) | 90%线(ms) | 95%线(ms) | 99%线(ms) | 吞吐量(/s) |
|---------|-------:|-------:|---------:|---------:|---------:|----------:|----------:|----------:|-----------:|
| 登录请求 | 300 | 0.00% | 52 | 22 | 112 | 76 | 79 | 82 | 18.8 |
| 浏览商品 | 300 | 0.00% | 32 | 11 | 68 | 47 | 49 | 54 | 18.8 |
| 下单请求 | 300 | 0.00% | 102 | 52 | 177 | 146 | 149 | 153 | 18.7 |
| **Total** | **900** | **0.00%** | **62** | **11** | **177** | **121** | **139** | **151** | **49.6** |

按性能测试的通用红线逐条检查:

1. **响应时间 > 3 秒?** 否。最大 177ms,持续时间断言零失败
2. **错误率 > 0.1%?** 否。900 样本 0 错误,登录提取 token → 下单鉴权的链路全部走通
3. **吞吐量上不去?** 49.6/s 看着不高,但这是被 1000±200ms 思考时间"压"出来的——这正是模拟真人的代价。去掉定时器重跑,吞吐量会直接取决于服务器容量

**结论**:被测服务在 100 并发下表现稳定,瓶颈在人为模拟的思考时间而非服务器本身,可以作为后续扩容压测的基线数据。

`report/index.html` 里还有响应时间随时间变化的曲线、每秒并发数、错误统计等可视化图表,比表格直观得多。

## 八、翻车现场与保命技巧

实践过程中遇到/预判的几个坑:

1. **下载超时**:JMeter 官方源国内极慢 → 换华为云镜像源
2. **中文乱码**:CSV 中文参数 → 文件编码指定 UTF-8
3. **内存溢出**:大压测前改 `jmeter.sh` 里的 `HEAP="-Xms1g -Xmx4g"`,按机器实际内存来
4. **结果文件撑爆硬盘**:`.jtl` 会记录每个样本,长稳测试记得只记错误样本或限制样本数
5. **监听器吃资源**:正式压测一律命令行模式,GUI 只用来调试脚本

## 九、总结

一次完整的 JMeter 压测闭环就是:**被测服务 → 参数化数据 → 带断言和思考时间的测试计划 → 冒烟验证 → 非GUI全量压测 → HTML报告分析**。

三条心得:

1. **脚本要像真人**:加思考时间、参数化、逻辑串联
2. **测试要像爬山**:5 → 100 → 更大,循序渐进
3. **分析要像侦探**:不只看平均值,重点看 90/95/99 分位线和错误率

以上完整脚本(`double11_test.jmx`)、被测服务源码(`mock_ecommerce_api.py`)、参数化数据(`users.csv`)和压测报告都在我的实践工程里,欢迎评论区交流。

**温馨提示**:压测前请务必在测试环境验证脚本,压测生产环境需提前知会相关人员。

---

*实践参考:华为云社区《JMeter压力测试,如何"温柔"地搞垮你的服务器?》,在此教程基础上完整落地了一遍流程。*

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。