1. 压力测试基础概念
压力测试(Stress Testing)是评估系统在超出正常容量极限时的行为表现。它不关注系统在预期负载下能否正常工作,而是回答一个问题:“系统在真正承受压力时,会在哪里、以什么方式崩溃?”。理解压力测试的核心概念,是后续所有参数测试、边界分析、阈值设定的先决条件。
参数含义:压力测试中的关键定量维度
在参数测试型课程中,压力测试拥有明确的可调参数。下表列出最核心的四个参数及其物理含义:
| 参数名称 | 符号 | 物理含义 | 单位 |
|---|---|---|---|
| 并发用户数 | C | 同时发送请求的虚拟用户数量 | 个 |
| 请求速率 | R | 单位时间内发出的请求数量 | req/s |
| 数据负载大小 | D | 单次请求携带的数据量(Payload) | KB/MB |
| 持续时长 | T | 压力保持的连续时间 | s / min |
这些参数并非独立——例如增大 C 通常也会引起 R 升高,直到系统资源耗尽。
测试条件:何时需要执行压力测试
- 前置条件:系统已完成功能测试和负载测试,功能基本稳定。
- 触发场景:电商秒杀、春晚红包、突发事件(如票务系统抢票)、DDoS 模拟。
- 环境要求:隔离的测试环境,避免干扰生产;资源监控(CPU、内存、IO)必须提前部署。
- 数据基线:需要已知系统的正常吞吐阈值(一般由负载测试获得)。
实践提示:第一次压力测试不要直接冲击极限。先设置 C = 1.5 倍预期最大并发,观察系统行为;若系统未崩溃,再逐步增加。
仪器/工具:常用压力测试引擎
| 工具 | 协议支持 | 脚本语言 | 特点 |
|---|---|---|---|
| Apache JMeter | HTTP/HTTPS, JDBC, JMS | Java / BeanShell | GUI 配置方便,支持分布式压测 |
| Locust | HTTP, gRPC | Python | 代码化压测,适合定制随机行为 |
| wrk / wrk2 | HTTP/1.1, HTTP/2 | Lua | 轻量、高并发,单机可达数十万请求 |
| Vegeta | HTTP | Go / YAML 配置 | 适合管道式持续压力攻击 |
工具选择取决于测试目标:如果关注应用层逻辑,用 JMeter 或 Locust;如果关注网络栈极限,用 wrk 或 Vegeta。
测量步骤:一次标准压力测试的流程
- 确定压力参数:选择 C、R、D、T 的初始值(通常参考负载测试极限值)。
- 预热阶段:以 10% 目标压力运行 30 秒,让 JIT、连接池达到稳态。
- 逐步加压:每隔 10 秒将压力增加 20%,记录每个台阶的响应时间与错误率。
- 保持峰值:在目标压力值上持压 T 时长(通常 ≥ 5 分钟)。
- 断崖下降:突然释放压力,观察系统恢复速度(是否会自动回缩资源)。
- 数据采集:收集吞吐量、延迟百分位、错误类型、资源使用率。
数据判断:如何识别系统已过载
压力测试的核心判断指标有三类——吞吐量拐点、延迟爆炸、错误率飙升。以下为一个典型压力测试的原始指标片段(真实场景的日志输出):
[2025-06-15 14:32:01] Concurrency=200 | RPS=4520 | p99=12ms | errors=0
[2025-06-15 14:32:11] Concurrency=300 | RPS=6400 | p99=18ms | errors=0
[2025-06-15 14:32:21] Concurrency=400 | RPS=6880 | p99=45ms | errors=2
[2025-06-15 14:32:31] Concurrency=500 | RPS=6900 | p99=120ms | errors=37
[2025-06-15 14:32:41] Concurrency=600 | RPS=6100 | p99=850ms | errors=294
可以看到在 C = 500 时:吞吐量(RPS)不再增长(拐点),延迟(p99)从 45ms 跳到 120ms,错误开始出现。此时系统已进入压力临界区。
误差分析:压力测试常见干扰因素
| 误差源 | 影响 | 缓解措施 |
|---|---|---|
| 资源虚拟化(容器/VM) | CPU 争抢导致延迟抖动 | 绑定物理核心;使用独占型实例 |
| 网络带宽限制 | 请求在中间设备排队 | 测试环境千兆直连;避免路由器 NAT |
| 数据量不足 | 缓存命中过高,掩盖真实瓶颈 | 使用随机数据,禁用缓存 |
| 压测节点瓶颈 | 压测工具自身 CPU/内存不足 | 使用分布式压测,监测压测机资源 |
| 定时预热不足 | JIT 编译导致的初期假象 | 固定预热 ≥ 30 秒且数据丢弃 |
重要:压力测试的误差如果不能被识别,会导致“过早失效线”误判。务必在每次测试前记录压测机的 CPU 负载,确保其空闲率 > 30%。
调参策略:压力参数调整优先级
- 第一优先:并发用户数(C) —— 最容易触发资源竞争。
- 第二优先:请求速率(R) —— 当 C 不变时,通过 R 可测试吞吐上限。
- 第三优先:数据负载大小(D) —— 主要影响 IO 和序列化开销。
- 第四优先:持续时长(T) —— 用于验证长期压力下的内存泄漏。
典型调参路径:先固定 D 和 T,线性增加 C 找到拐点;再在拐点处调整 R 以精细识别瓶颈是 CPU 还是 IO。
验收阈值:压力测试通过标准
验收阈值需要与性能指标绑定,常见的参数化验收公式为:
// 验收阈值示例(JSON)
{
"stress_test_acceptance": {
"max_response_time_p99": 500, // ms
"max_error_rate": 0.01, // 1%
"min_throughput_at_peak": 5000, // req/s
"recovery_time_after_release": 30 // seconds
}
}
若在峰值压力下满足以上四项条件,则系统通过压力验收。任何一项超出阈值即判定为失败,需返回调参循环重新测试。
章节小结:压力测试的核心是系统化地调大压力参数,找到系统在 C、R、D、T 交叉作用下的失效点。本章建立了概念共识:参数含义、测试条件、工具选择、测量流程、数据判读方法、误差来源、调参顺序以及验收阈值标准。从下一章开始,我们将逐一深入每个参数的边界测试技术。