| name | performance-testing |
| description | 评估系统性能 / 容量 / 压测时使用。适用于上线前性能基线、SLA 验证、容量规划、性能退化排查。融合 Google SRE Workbook、Brendan Gregg USE Method、k6/JMeter 实践。 |
性能测试(Performance Testing)
参考来源:Google《Site Reliability Engineering》、Brendan Gregg《Systems Performance》USE Method、k6 Best Practices、JMeter Patterns。
适用场景
- 上线前建立性能基线
- SLA / SLO 验证
- 容量规划(多少机器够用)
- 性能退化排查(vs 上版本)
- 大促 / 高并发活动前压测
- 数据库 / 缓存 / 队列容量评估
核心原则
1. 先定义 SLO,再压测
不知道目标的压测毫无意义
2. 测试数据接近生产
小数据量测出来都是假的
3. 测的是"系统行为",不是峰值数字
长时间运行 + 资源监控 + 瓶颈分析
4. 基线对比比绝对值更重要
"比上版本退化 30%" 比 "QPS 1000" 更有用
5. 性能问题留到生产 = 事故
QA 必须在测试环境提前发现
性能测试类型
负载测试(Load Test)
- 目的:验证正常负载下系统稳定性
- 场景:QPS 100,持续 10 分钟
- 关注:响应时间、错误率
压力测试(Stress Test)
- 目的:找系统极限
- 场景:QPS 从 100 逐渐增加到崩溃
- 关注:拐点、极限 QPS、降级行为
浸泡测试(Soak / Endurance Test)
- 目的:长时间稳定性(内存泄漏 / 资源耗尽)
- 场景:QPS 100 持续 8 小时
- 关注:内存增长、连接池耗尽、GC
尖峰测试(Spike Test)
- 目的:突发流量恢复能力
- 场景:QPS 100 → 突增到 5000 → 回到 100
- 关注:恢复时间、是否雪崩
容量测试(Capacity Test)
- 目的:单实例吞吐 / 资源消耗
- 场景:固定 QPS,记录 CPU/Memory/IO
- 关注:每核 QPS、内存增长率
关键指标
响应时间
P50:50% 用户 < X ms(中位数)
P95:95% 用户 < X ms
P99:99% 用户 < X ms(关键指标)
Max:最大响应时间
注意:永远看 P99 不看平均值
平均值会被极快或极慢拉偏
吞吐量
QPS:每秒查询数(读)
TPS:每秒事务数(写)
RPS:每秒请求数
注意:QPS 不是越高越好
要在 SLO 范围内的 QPS
错误率
错误率 = 失败请求 / 总请求
SLO 通常 < 0.1% / 1%
资源利用率(USE Method)
Utilization:使用率(CPU / Memory / Disk)
Saturation:饱和度(队列长度 / 等待时间)
Errors:错误数(错误日志 / 异常)
每种资源都问这三个问题
SLO 模板
模块:[订单创建 API]
成功 SLO:
- 99% 请求 P99 < 500ms
- 错误率 < 0.5%
- QPS >= 1000
容量 SLO:
- 单实例支持 QPS >= 200
- 内存使用 < 512MB
- CPU 使用 < 70%
退化告警:
- P99 > 800ms 持续 5 分钟
- 错误率 > 1% 持续 1 分钟
工作流程
1. 定义 SLO
- 与 PM、SRE 对齐目标
↓
2. 准备测试数据
- 接近生产规模
- 真实分布(80% 主路径 + 20% 边缘)
↓
3. 准备测试环境
- 与生产同配置
- 监控接好(Prometheus / DataDog)
↓
4. 编写测试脚本
- k6 / JMeter / Locust / Gatling
↓
5. 执行
- 先小规模冒烟
- 再按场景执行
↓
6. 监控数据
- QPS / 响应时间 / 错误率
- CPU / Memory / IO / Network
- 数据库 / 缓存 / 队列
↓
7. 分析瓶颈
- 用 USE Method
- 看慢查询日志
- 看应用 trace
↓
8. 输出报告
- SLO 是否达标
- 瓶颈在哪
- 容量结论
- 与上版本对比
↓
9. 给 SRE / 开发改进建议
测试数据准备
规模:
- 用户数:生产规模 80%~100%
- 订单数:生产规模 80%~100%
- 数据分布:模拟真实(新用户 / 活跃 / 沉睡)
数据生成:
- 工具:generators / faker / 业务工具
- 性能:百万级 < 1 小时
- 隔离:独立 schema / 标记 _test_
冷启动 vs 热启动:
- 冷启动:缓存空,第一次请求
- 热启动:缓存预热后稳定
- 都要测
工具对比
| 工具 | 语言 | 优势 | 劣势 |
|---|
| k6 | JavaScript | 现代、CI 友好、报告好 | 不支持 GraphQL(直接) |
| JMeter | Java | 老牌、GUI、插件多 | 重、性能开销大 |
| Locust | Python | 易写脚本、分布式 | 性能不如 k6/Gatling |
| Gatling | Scala | 高性能、报告漂亮 | 学习曲线 |
| wrk | C | 极致性能 | 功能简单 |
| ab | C | 入门快速 | 单线程、功能少 |
推荐:k6 作为主力 + wrk 作为快速基线。
常见瓶颈
1. 数据库
- 慢查询 / 锁冲突 / 连接池满
- 解:索引 / 缓存 / 读写分离 / 分库分表
2. 缓存
- 缓存穿透 / 击穿 / 雪崩
- 解:布隆过滤器 / 热点预热 / 多级缓存
3. 应用
- GC 频繁 / 内存泄漏 / 线程池满
- 解:调 JVM / 异步化 / 解决泄漏
4. 网络
- 带宽瓶颈 / TCP 连接耗尽
- 解:长连接 / CDN / 增加带宽
5. 第三方
- 调用慢 / 超时 / 限流
- 解:异步 / 缓存 / 降级
6. 配置
- 线程池 / 连接池 / 超时配置
- 解:调参(先压测再调)
容量规划公式
所需实例数 = 总 QPS / 单实例 QPS × Buffer
示例:
目标 QPS = 5000
单实例 QPS = 200
Buffer = 1.5(应对突发)
实例数 = 5000 / 200 × 1.5 = 38 个
然后按 N+1 / N+2 容灾:
→ 实际部署 40 个
质量自检
□ SLO 已与 PM/SRE 对齐
□ 测试数据规模接近生产
□ 测试环境与生产同配置
□ 监控完整(应用 / 数据库 / 缓存 / 队列)
□ 测了主要场景(负载 / 压力 / 浸泡)
□ 浸泡测试 ≥ 1 小时
□ 尖峰测试做了
□ 瓶颈分析到根因
□ 与上版本基线对比
□ 容量结论给 SRE
□ 改进建议给开发
常见坑
- 不定 SLO 就压测——压出来不知道好坏
- 测试数据太小——10 条数据测出来都快
- 只看平均值——P99 才是关键
- 不监控资源——只看 QPS 不看 CPU/Memory
- 冷启动不算——第一次请求慢被忽略
- 只测主路径——边缘场景压垮系统
- 不做浸泡测试——内存泄漏只在 8 小时后出现
- 测试环境与生产差异大——结论不可信
- 第三方不 Mock——压坏第三方
- 压测后不分析——只丢一份数字给开发
- 忽略 GC——P99 抖动就是 GC 引起
- 不留 Buffer——满载部署,突发就崩
配套模板
templates/perf-baseline-template.md — SLO + 测试场景 + 结果数据 + 瓶颈分析 + 容量结论 + 与上版本基线对比
与其他 skill 的协作
上游:
test-strategy → 性能测试范围
test-data-management → 大规模测试数据
下游:
bug-reporting → 性能问题转 Bug
test-report → 性能结论纳入报告
quality-gate → SLO 作为放行条件
SRE/运维工作流 → 监控告警建议
DevOps 工作流 → 容量规划