2. 压力测试基础回顾
压力测试是性能工程的核心环节,其目标是通过模拟高于预期的并发负载,观察系统在极限状态下的行为表现。本节将系统梳理压力测试的核心概念、关键度量指标以及主流工具,为后续章节的特征服务与情景分析奠定基础。
2.1 压力测试概念与目标
压力测试(Stress Testing)与负载测试(Load Testing)常被混淆,二者在目标与手段上有本质区别:
| 维度 | 负载测试 | 压力测试 |
|---|---|---|
| 核心目标 | 验证系统在预期负载下的性能是否达标 | 发现系统在超载时的瓶颈与崩溃点 |
| 负载特征 | 逐步增加至目标并发数,保持稳定 | 持续增加直至系统过载或失败 |
| 关注重点 | 响应时间、吞吐量、资源利用率 | 错误率、恢复能力、降级行为 |
| 典型场景 | 日常高峰流量模拟 | 秒杀、DDoS 攻击、突发流量 |
| 结束条件 | 达到目标负载且系统稳定 | 系统出现明显错误或性能拐点 |
关键认知:压力测试不是为了证明系统"能跑多快",而是为了回答"系统在什么条件下会崩溃,以及崩溃后如何恢复"。
2.2 核心性能指标
压力测试的量化分析依赖三个黄金指标:TPS、响应时间、错误率。三者共同构成系统健康度的"铁三角"。
2.2.1 TPS(每秒事务数)
TPS 是衡量系统处理能力最直接的指标,代表系统每秒能够完成的事务数量。事务可以是单个 API 请求,也可以是包含多个步骤的业务操作。
- 峰值 TPS:系统在短时间内能达到的最大吞吐量。
- 稳定 TPS:系统在持续压力下能长期维持的吞吐量。
- 拐点 TPS:当负载继续增加时,TPS 不再线性增长反而下降的临界点。
2.2.2 响应时间
响应时间反映系统对单个请求的处理速度,通常关注以下分位值:
| 分位值 | 含义 | 典型阈值(参考) |
|---|---|---|
| P50(中位数) | 一半请求的响应时间低于此值 | < 200ms |
| P90 | 90% 的请求在此时间内完成 | < 500ms |
| P99 | 99% 的请求在此时间内完成 | < 1000ms |
| Max | 最慢请求的响应时间 | 通常不设硬性阈值 |
2.2.3 错误率
错误率是压力测试中判断系统是否"健康"的底线指标。常见的错误类型包括:
- HTTP 5xx:服务端内部错误,通常表示系统过载或代码异常。
- 超时错误:请求在指定时间内未收到响应。
- 连接拒绝:服务端连接池耗尽或进程崩溃。
- 业务错误:返回 HTTP 200 但业务逻辑失败(如库存扣减失败)。
实践建议:在压力测试中,错误率应严格控制在 0.1% 以下。一旦错误率超过 1%,应立即停止加压并分析根因。
2.3 常见压力测试工具简介
业界主流的压力测试工具各具特色,选择时需结合团队技术栈、测试场景复杂度以及报告需求。以下对 JMeter 和 Locust 进行对比分析。
2.3.1 Apache JMeter
JMeter 是 Apache 基金会旗下的纯 Java 压测工具,拥有最广泛的生态支持。
- 架构:基于线程组(Thread Group)驱动,每个线程模拟一个虚拟用户。
- 协议支持:HTTP/HTTPS、JDBC、JMS、FTP、TCP 等 20+ 协议。
- 优势:GUI 界面直观,插件生态丰富(如 PerfMon、Backend Listener),支持分布式压测。
- 局限:脚本编写依赖 GUI 配置,复杂逻辑需编写 Java 代码;资源消耗较高。
2.3.2 Locust
Locust 是基于 Python 的事件驱动压测工具,以代码定义用户行为。
- 架构:基于协程(gevent)实现高并发,每个用户是一个轻量级协程。
- 协议支持:原生支持 HTTP/HTTPS,其他协议可通过自定义客户端扩展。
- 优势:Python 脚本灵活可控,Web UI 实时监控,支持分布式且资源占用低。
- 局限:协议扩展需自行开发,报告功能相对 JMeter 较弱。
| 对比维度 | JMeter | Locust |
|---|---|---|
| 开发语言 | Java | Python |
| 并发模型 | 多线程(重量级) | 协程(轻量级) |
| 脚本方式 | GUI 配置 + 少量代码 | 纯代码(Python) |
| 协议扩展 | 插件丰富,扩展方便 | 需自行编写客户端 |
| 实时监控 | 命令行 + 插件 | Web UI 原生支持 |
| 分布式支持 | 原生支持(Master-Slave) | 原生支持(Master-Worker) |
| 学习曲线 | 中等(GUI 易上手,高级功能复杂) | 较低(需 Python 基础) |
2.4 压力测试基本流程
一次完整的压力测试通常遵循以下步骤:
- 场景定义:明确测试目标(如"系统能否支撑 1000 并发用户")和业务场景(如"用户登录→浏览商品→下单")。
- 脚本开发:使用 JMeter 或 Locust 编写压测脚本,包含请求参数、断言、关联提取等。
- 环境准备:确保测试环境与生产环境配置一致(或按比例缩容),监控工具就绪。
- 基准测试:以低并发(如 1 个用户)运行,验证脚本正确性并获取基线数据。
- 阶梯加压:逐步增加并发用户数(如 10→50→100→200→500),记录每个阶梯的 TPS、响应时间、错误率。
- 极限探测:持续加压直到系统出现明显错误或性能拐点,记录最大承载能力。
- 结果分析:结合监控数据(CPU、内存、IO、网络)定位瓶颈,输出测试报告。
常见误区:不要在压力测试中直接跳到目标并发数。缺少阶梯加压过程,你将无法发现性能拐点,也无法判断系统是"稳定承载"还是"勉强支撑"。