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%,应立即停止加压并分析根因。
压力测试核心指标铁三角 TPS(吞吐量) 响应时间 错误率 三个指标相互制约:TPS 升高 → 响应时间增加 → 错误率上升 找到三者的平衡点是压力测试的核心目标

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 基础)
JMeter vs Locust 架构对比 JMeter 架构(多线程) 线程组 线程组 线程组 线程组 Locust 架构(协程) 协程池 协程池 协程池 协程池 JMeter 每个线程对应一个 OS 线程,并发数受限于系统资源 Locust 每个协程仅占用 KB 级内存,单机可轻松模拟数千用户 选型建议 • 团队 Java 技术栈 / 需要丰富协议支持 / 重视报告 → 选择 JMeter • 团队 Python 技术栈 / 需要灵活脚本 / 追求轻量级 → 选择 Locust

2.4 压力测试基本流程

一次完整的压力测试通常遵循以下步骤:

  1. 场景定义:明确测试目标(如"系统能否支撑 1000 并发用户")和业务场景(如"用户登录→浏览商品→下单")。
  2. 脚本开发:使用 JMeter 或 Locust 编写压测脚本,包含请求参数、断言、关联提取等。
  3. 环境准备:确保测试环境与生产环境配置一致(或按比例缩容),监控工具就绪。
  4. 基准测试:以低并发(如 1 个用户)运行,验证脚本正确性并获取基线数据。
  5. 阶梯加压:逐步增加并发用户数(如 10→50→100→200→500),记录每个阶梯的 TPS、响应时间、错误率。
  6. 极限探测:持续加压直到系统出现明显错误或性能拐点,记录最大承载能力。
  7. 结果分析:结合监控数据(CPU、内存、IO、网络)定位瓶颈,输出测试报告。
常见误区:不要在压力测试中直接跳到目标并发数。缺少阶梯加压过程,你将无法发现性能拐点,也无法判断系统是"稳定承载"还是"勉强支撑"。