PERF TEST · 压测指标 / 瓶颈定位
性能测试速查
从指标口径、压测类型到 JMeter / wrk 工具上手,再到瓶颈定位思路与调优速赢清单,软件测试方向最常用的 52 条要点一张表收齐,随查随用。
52条要点
8大主题
∞持续更新
📖 速查表
点击展开各小节
📊 核心指标
指标先统一定义再开压:事务边界、统计口径不一致,两份数据没有可比性。
| 指标 | 定义 | 关系与参考口径 |
|---|---|---|
| RT 响应时间 | 从发起请求到收到完整响应的耗时,衡量用户体感速度 | 看 P95/P99 而非平均值;接口类通常要求 P99 < 200ms |
| TPS 每秒事务数 | 系统每秒完成的完整业务事务数,是吞吐量的核心口径 | 一次事务可能含多次请求/查询,与 QPS 换算时要先定义事务边界 |
| QPS 每秒查询数 | 系统每秒处理的请求数,接口粒度的吞吐指标 | 一次事务含 N 次调用时 QPS = TPS × N 先定边界再对比 |
| 并发数(VU) | 同一时刻与系统交互的虚拟用户数,模拟在线用户同时操作 | 并发数 ≠ 每秒请求数;它由压测工具施加,吞吐是系统产出的结果 |
| 错误率 | 失败请求占总请求的比例(超时、5xx、断言失败都计入) | 核心链路通常要求 < 0.1%;错误率拐点常早于 RT 恶化出现 |
| Little's Law | 排队论基本定律,串联并发、吞吐与响应时间三者的关系 | 并发数 = TPS × RT,如 TPS=200、RT=0.5s → 需 100 并发 估算并发必备 |
| P95 / P99 分位线 | 95% / 99% 的请求 RT 不超过该值,刻画长尾延迟 | 平均值会被少量快请求稀释,长尾问题必须看分位线 比均值更能暴露问题 |
🧪 压测类型
| 类型 | 目的 | 时长与成功标准 |
|---|---|---|
| 基准测试 | 低并发下摸清单请求 RT 与单节点容量基线,作为后续对比的参照物 | 短时长(分钟级);成功标准:RT 基线稳定、无错误 一切对比的起点 |
| 负载测试 | 按预期业务负载逐级加压,验证系统能否在目标并发下达标 | 每级梯度稳定运行数分钟;成功标准:达到目标 TPS 且 P99、错误率达标 |
| 压力测试 | 持续加压超过预期负载,找出系统极限容量与崩溃拐点 | 加压至系统劣化为止;成功标准:明确极限值、劣化方式可控(限流降级而非雪崩) |
| 稳定性测试 | 正常负载下长时间持续运行,暴露内存泄漏、连接泄漏、日志膨胀等问题 | 7×24h 量级;成功标准:RT 无漂移、内存曲线平稳 看趋势不看瞬时 |
| 尖峰测试 | 瞬时流量陡增(秒杀、整点抢购),验证扩容、限流与队列兜底能力 | 秒级瞬时打到峰值;成功标准:峰值期错误率可控、峰值后快速恢复 |
| 冲浪测试 | 流量按真实曲线波动起伏,验证弹性伸缩与缓存命中率在波动下的表现 | 小时~天级循环波峰波谷;成功标准:扩缩容跟得上、波谷后资源能回收 |
🛠️ 工具速用
| 工具 / 组件 | 说明 | 示例 |
|---|---|---|
| JMeter 线程组 | 定义并发模型:线程数即并发用户,Ramp-Up 控制爬坡速度,可按持续时间或循环次数运行 | 线程数 200、Ramp-Up 60s、持续 30min 先小后大梯度加 |
| JMeter 取样器 + 断言 | HTTP 取样器发起请求;响应断言校验状态码与业务字段——没有断言的压测结果不可信 | 响应断言:状态码 200 + 包含 "code":0 |
| JMeter 监听器 | 聚合报告查看吞吐、P90/P95 与错误率;正式压测用 CLI 模式,禁用 GUI 监听防止施压机成为瓶颈 | jmeter -n -t plan.jmx -l result.jtl GUI 只调试用 |
| JMeter 参数化 CSV | CSV Data Set Config 读取测试数据,用变量替换请求参数,避免同一请求被缓存命中造成假吞吐 | CSV 列 userId → 请求体引用 ${userId} |
| wrk | 轻量高性能压测命令行工具,单机即可施压大量连接,适合接口级快速验证 | wrk -t12 -c400 -d30s --latency http://host/api # 12 线程、400 连接、压 30 秒 |
| ab | Apache 自带的极简压测工具,一条命令快速冒烟,不适合复杂场景 | ab -n 1000 -c 100 http://host/path 1000 请求 100 并发 |
| 监控工具组合 | 压测必须同时盯两头:施压侧与被测侧,各层各司其职 | top 看主机、JConsole/Arthas 看 JVM、Prometheus + Grafana 看全局曲线 |
📋 压测流程
| 阶段 | 关键动作 | 产出 |
|---|---|---|
| ① 明确目标 | 和业务对齐量化指标:目标 TPS、P99 上限、错误率红线,避免"压一压看看"式压测 | 指标基线,如"支撑 5000 QPS,P99 < 200ms,错误率 < 0.1%" 可量化才可验收 |
| ② 场景设计 | 梳理核心业务链路并分配流量比例(如查询:下单 = 8:2),准备足量测试数据 | 压测场景模型 + 数据准备清单 |
| ③ 脚本准备 | 录制或编写脚本,完成参数化、添加断言、剥离 GUI 依赖,并在低并发下先验证脚本正确性 | 可复用的压测脚本(jmx / wrk 脚本) |
| ④ 梯度加压 | 并发从低到高阶梯递增(如 50→100→200→400),每级稳定运行数分钟再继续,禁止一步到位 | 各梯度吞吐/RT 数据,找到性能拐点 拐点 = 容量边界 |
| ⑤ 监控采集 | 同一时间窗内采集应用(RT/错误率)、主机(CPU/IO/带宽)、中间件(连接池/GC/慢 SQL)三层指标 | 全链路监控数据,能对上时间轴 |
| ⑥ 分析调优 | 对照拐点定位瓶颈层,做一轮只改一处的优化,然后复测对比,避免多项改动互相污染结论 | 瓶颈分析报告 + 调优项清单 |
| ⑦ 回归验证 | 调优后按完全相同的场景与梯度复测,确认指标达标且无功能回归,沉淀为报告归档 | 压测报告(含前后对比与剩余风险) |
🩺 瓶颈定位
先定位瓶颈在哪一层(施压机 / 应用 / 中间件 / DB),再谈优化;跳过定位直接调参是白忙。
| 症状 | 可能原因 | 排查手段 |
|---|---|---|
| CPU 持续打高 | 死循环、频繁 GC、序列化/加解密开销过大 | top -Hp <pid> 找高 CPU 线程 → printf '%x' 转十六进制查 jstack;Arthas thread -n 3 直接看热点 先分用户态还是 GC |
| RT 突增 | 下游变慢(DB、外部接口)、锁竞争、Full GC 停顿 | 看 GC 日志与慢查询日志;链路追踪(SkyWalking)按 span 拆耗时分层归因 |
| 错误率上升 | 连接池耗尽、线程池打满、依赖超时、OOM | 错误日志关键字(timeout / refused / OutOfMemory)+ 线程 dump 分析 |
| 吞吐上不去 | 线程数/连接数不足、限流阈值过低、同步阻塞 IO | 核对施压参数与线程池配置;确认瓶颈在客户端还是服务端再加压 先排除施压机瓶颈 |
| GC 频繁 | 堆偏小、大对象分配、缓存无界膨胀 | 开启 -Xlog:gc*,看 Young/Full GC 频率与单次耗时,配合堆转储找大对象来源 |
| 慢 SQL | 缺索引、大表全扫、深分页、隐式类型转换导致索引失效 | EXPLAIN 看执行计划;开启慢查询日志 slow_query_log 按 RT 排序逐一治理 |
| 连接池耗尽 | 池容量偏小、慢查询占住连接不释放、连接泄漏未归还 | 监控活跃/空闲连接数曲线;检查借出未归还的代码路径与超时配置 |
| 网络瓶颈 | 带宽打满、TCP 重传率高、大量短连接 | sar -n DEV 看网卡流量,ss -s 看连接统计与 TIME_WAIT 状态 |
🎯 调优速赢清单
| 优化项 | 做法 | 预期收益 |
|---|---|---|
| 连接池参数 | maxPoolSize 按"并发 × RT + 余量"估算并压测校准,minIdle 预热避免冷启动建连 | 消除获取连接等待,吞吐提升且更平稳 改动小见效快 |
| 缓存引入 | 热点数据加 Redis/本地缓存,用互斥锁或逻辑过期防击穿,注意空值缓存防穿透 | DB 压力骤降,命中请求 RT 降到毫秒内 |
| 异步化 | 非核心链路(通知、日志、积分)改 MQ 异步削峰,主链路只保留必需同步逻辑 | 主链路 RT 下降,峰值吞吐上升 先砍旁路再扩容 |
| SQL 索引 | 为 WHERE / ORDER BY / JOIN 列建联合索引,避免 select * 与索引列上做函数运算 | 慢查询从秒级降到毫秒级,连接占用随之减少 |
| JVM 堆参数 | -Xms 与 -Xmx 设为同值避免动态扩容抖动;堆大小约为容器内存的一半并留足元空间与堆外 | 减少 Full GC 触发,RT 曲线更平滑 |
| GC 选型与参数 | 大堆低延迟场景选 -XX:+UseG1GC(配 -XX:MaxGCPauseMillis=200)或 -XX:+UseZGC | P99 明显改善,长尾抖动收敛 先测后调,一次一参 |
📋 压测报告要素
压测的价值一半在执行、一半在报告:结论先行、环境可复现、数据成链路、风险有归属,报告才能驱动决策而不是归档了事。
| 要素 | 内容要求 | 常见缺失后果 |
|---|---|---|
| 目标与结论先行 | 第一页写清压测目标与「达标 / 不达标」结论,正文再展开论证,读的人十秒内拿到答案 | 结论埋在末尾没人看,报告沦为流水账 结论前置 |
| 环境说明 | 机器规格、部署拓扑、版本号逐项列出;环境与生产等量还是缩比、测试数据造了多少条,必须写明 | 等比缩小环境却按生产给结论,误导容量评估 可复现的前提 |
| 场景与模型 | 业务链路、流量配比(如查询 : 下单 = 8 : 2)、加压曲线(梯度 / 尖峰 / 波浪)与压测时长 | 只报数字不说场景,结论无法迁移复用 加压曲线必附 |
| 核心指标表 | 各并发梯度下的 TPS、P95/P99、错误率与资源占用(CPU / 内存 / IO)对照,标出拐点位置 | 只给平均值掩盖长尾,拐点凭印象描述 分位线 + 拐点 |
| 瓶颈与调优记录 | 每轮瓶颈的定位依据、改动项、复测对比数据;一轮只改一处,改动与收益一一对应 | 多项混改说不清谁的功劳,无法沉淀经验 一轮一改一复测 |
| 遗留风险与建议 | 未达标项、已知风险、当前容量水位与扩容触发条件、下一步建议,逐项写明负责人 | 报告通过即归档,风险无人跟进 风险必须有 owner |
🧮 容量推算示例
上线前被问「能扛多少量」时,按这条链路从业务数字推到技术容量:日活 → 峰值 QPS → 并发 → 连接与带宽,每一步都可验算、可复核。
| 推算环节 | 公式与经验值 | 示例 |
|---|---|---|
| 日活 → 峰值 QPS | 二八原则:80% 的请求集中在 20% 的时间里;峰值 QPS ≈ 日请求量 × 0.8 ÷ (86400 × 0.2),再乘 2~3 倍冗余系数 | 日均 1000 万次请求 → 峰值约 463 QPS,按 1000+ 设计 二八原则 |
| QPS → 并发数 | Little's Law:并发数 = QPS × 平均 RT(秒);RT 按目标上限代入,不要用实测值倒推 | 目标 1000 QPS、RT 0.2s → 200 并发 Little's Law |
| 并发 → 连接池大小 | 连接数 ≈ 并发数 × 该链路 DB 调用占比 + 20% 余量;先按估算起步,压测校准后固化 | 200 并发、DB 调用占 50% → 起步 120,压测定型 压测校准 |
| 带宽估算 | 出口带宽 (Mbps) ≈ QPS × 平均响应大小 (KB) × 8 ÷ 1000;静态资源先确认走 CDN 再算 | 1000 QPS × 50KB × 8 ≈ 400 Mbps 静态走 CDN |
| 缓存命中率的杠杆 | 回源量 = 总 QPS × (1 - 命中率);命中率从 90% 提到 99%,DB 压力直接降为原来的 1/10 | 10 万 QPS、命中率 95% → DB 只承受 5000 QPS 命中率即容量 |