性能测试
一、性能测试概述
1.1 什么是性能测试
性能测试是通过模拟大量用户并发访问系统,评估系统在不同负载条件下的响应速度、稳定性、可靠性和资源消耗,从而发现性能瓶颈和系统的最大处理能力。
1.2 性能测试的目的
- 验证系统是否满足预期的性能指标(SLA)
- 发现系统的性能瓶颈(数据库、网络、代码逻辑等)
- 评估系统的最大承载能力和扩展性
- 为容量规划和资源配置提供数据支撑
- 确保系统在高并发场景下的稳定性
1.3 性能测试类型
|
测试类型 |
目的 |
执行方式 |
|---|---|---|
|
负载测试(Load Testing) |
验证系统在预期负载下的性能表现 |
模拟正常业务峰值并发量 |
|
压力测试(Stress Testing) |
找出系统的最大承载能力和崩溃点 |
逐步增加负载直到系统崩溃 |
|
容量测试(Capacity Testing) |
验证系统能否处理预期的最大数据量 |
使用大数据集进行测试 |
|
稳定性测试(Endurance Testing) |
验证系统长时间运行的稳定性 |
持续运行数小时甚至数天 |
|
尖峰测试(Spike Testing) |
验证系统应对突发流量的能力 |
短时间内急剧增加负载 |
二、核心性能指标详解
2.1 吞吐量(Throughput)
QPS(Queries Per Second)
- 定义:每秒查询数,表示系统每秒能处理的查询请求数量
- 衡量方式:在持续施压条件下,统计每秒成功响应的请求总数
- 作用:衡量系统在高并发场景下的处理能力上限
- 计算公式:QPS = 总请求数 / 测试持续时间(秒)
TPS(Transactions Per Second)
- 定义:每秒事务数,表示系统每秒能完成的业务事务数量
- 与 QPS 的区别:一个事务可能包含多个请求(如登录 = 验证码 + 密码校验 + 生成 token),TPS 更贴近业务视角
- 典型参考值:小型系统 100-500 TPS、中型系统 500-5000 TPS、大型系统 5000+ TPS
点击率(Hits Per Second)
- 定义:每秒 HTTP 请求总数(包括所有静态资源请求)
2.2 响应时间(Latency / Response Time)
|
指标 |
定义 |
作用 |
|---|---|---|
|
平均响应时间(Avg RT) |
所有请求响应时间的算术平均值 |
整体性能的粗略衡量 |
|
最小响应时间(Min RT) |
测试中观测到的最快响应 |
理想条件性能下限 |
|
最大响应时间(Max RT) |
测试中观测到的最慢响应 |
最差情况的极端值 |
|
P50(中位数) |
50% 的请求响应时间 ≤ 该值 |
典型用户体感 |
|
P90 |
90% 的请求响应时间 ≤ 该值 |
大多数用户的体感 |
|
P95 |
95% 的请求响应时间 ≤ 该值 |
反应尾部延迟 |
|
P99 |
99% 的请求响应时间 ≤ 该值 |
对实时性要求高的系统尤为重要 |
为什么看分位数而不是平均值? 假设 100 个请求中 95 个在 100ms 内完成,5 个耗时 10 秒。平均值 = (95×100 + 5×10000)/100 = 595ms,看起来还可以,但实际有 5% 的用户体验极差。P99 能真实反映"最慢的那批用户"的体感。
响应时间分段标准(Web 应用参考)
|
等级 |
响应时间 |
用户体验 |
|---|---|---|
|
优秀 |
≤ 100ms |
即时响应,无感知延迟 |
|
良好 |
100ms - 300ms |
可感知但流畅 |
|
正常 |
300ms - 1s |
可接受,稍有延迟感 |
|
较差 |
1s - 3s |
明显等待,体验不佳 |
|
不可接受 |
> 3s |
用户可能离开 |
2.3 错误率(Error Rate / Failure Rate)
- 定义:一段时间内失败请求数占总请求数的比例
- 计算公式:错误率 =(失败请求数 / 总请求数)× 100%
- 失败判定标准:HTTP 状态码非 2xx/3xx、业务错误码、请求超时、连接被拒绝
- SLA 参考:通常要求 ≤ 0.1%,优秀 ≤ 0.01%(万分之一)
2.4 并发量(Concurrency)
并发用户数(Concurrent Users)
- 定义:同一时刻与系统交互的虚拟用户数
- 注意区分:并发用户数 ≠ 在线用户数(在线用户可能没有主动发请求)
公式:TPS = 并发用户数 / 平均响应时间 例如:100 个并发用户,平均响应时间 200ms(0.2s),则 TPS = 100 / 0.2 = 500
2.5 PV 与 UV
- PV(Page View):页面浏览量,用户每次访问页面计为一次 PV
- UV(Unique Visitor):独立访客数,通常按天去重统计
- 运维参考:通过 PV/UV 推算系统需要的 QPS 承载能力
三、系统资源指标
3.1 CPU 使用率
|
指标 |
说明 |
告警阈值参考 |
|---|---|---|
|
CPU 总体使用率 |
所有核心的平均使用率 |
> 70% 关注,> 90% 告警 |
|
CPU 单核使用率 |
单核心的使用率 |
若单核持续 > 90%,可能存在单线程瓶颈 |
|
CPU 用户态(us) |
应用代码消耗 |
占比高说明计算密集 |
|
CPU 内核态(sy) |
系统调用消耗 |
占比高说明 I/O 密集 |
|
CPU 等待 I/O(wa) |
等待磁盘 I/O 的 CPU 时间 |
> 10% 说明磁盘是瓶颈 |
# 实时查看 CPU 使用率
top
htop
# 查看 CPU 详细信息
mpstat -P ALL 2 5
# 查看系统平均负载
uptime
3.2 内存使用率
|
指标 |
说明 |
|---|---|
|
已用内存(Used) |
当前已分配使用的内存 |
|
可用内存(Available) |
可分配给新进程的内存(含可回收的缓存) |
|
缓存/缓冲区(Buff/Cache) |
用于文件缓存的内存,必要时可释放 |
|
交换分区使用(Swap) |
使用 Swap 说明物理内存已不足,性能会急剧下降 |
free -h # 查看内存使用概况
top -o %MEM # 按内存使用排序
sar -r 2 10 # 持续监控内存
3.3 磁盘 I/O
|
指标 |
说明 |
关注点 |
|---|---|---|
|
IOPS |
每秒读写操作次数 |
随机 I/O 瓶颈的主要指标 |
|
吞吐量(MB/s) |
每秒读写的数据量 |
顺序读写的主要指标 |
|
读/写延迟(await) |
I/O 操作的平均等待时间 |
> 10ms 需关注 |
|
磁盘队列长度(avgqu-sz) |
等待 I/O 的请求数量 |
持续 > 1 说明磁盘处理不过来 |
|
磁盘使用率(%util) |
磁盘繁忙时间占比 |
> 80% 需关注 |
iostat -x 2 5 # 查看磁盘 I/O 统计
iotop # 实时查看磁盘读写
pidstat -d 2 5 # 查看进程的磁盘 I/O 详情
3.4 系统平均负载(Load Average)
uptime
# 输出示例:load average: 1.50, 2.30, 2.80
# 分别表示:1分钟、5分钟、15分钟的平均负载
- 定义:单位时间内处于可运行状态(R)和不可中断睡眠状态(D)的进程平均数
- 判断标准:Load < CPU 核心数 → 正常;Load ≈ CPU 核心数 → 满负荷;Load > CPU 核心数 → 过载
3.5 网络指标
|
指标 |
说明 |
|---|---|
|
网络带宽使用率 |
网卡入/出流量(Mbps) |
|
连接数 |
TCP 连接数(ESTABLISHED / TIME_WAIT / CLOSE_WAIT) |
|
丢包率 |
数据传输中的丢包比例 |
|
网络延迟(RTT) |
数据包往返时间 |
sar -n DEV 2 5 # 查看网络流量
ss -s # 查看网络连接统计
ping -c 10 example.com # 查看网络延迟
四、后端依赖性能指标
4.1 数据库性能指标
|
指标 |
说明 |
关注点 |
|---|---|---|
|
慢查询数量 |
执行时间超过阈值的 SQL |
阈值通常设为 100-200ms |
|
连接池使用率 |
活跃连接数 / 最大连接数 |
> 70% 需关注 |
|
查询 QPS |
每秒处理的查询数 |
衡量数据库负载 |
|
锁等待时间 |
事务等待锁的时长 |
过长影响并发 |
|
主从延迟 |
主库到从库的数据延迟 |
读写分离时影响一致性 |
|
缓存命中率 |
Buffer Pool / Query Cache 命中率 |
低命中率说明内存不够 |
4.2 缓存性能指标(Redis 等)
|
指标 |
说明 |
告警参考 |
|---|---|---|
|
缓存命中率 |
命中次数 / 总请求次数 |
< 90% 需分析 |
|
内存使用率 |
已用 / 最大内存 |
> 80% 需关注 |
|
连接数 |
当前客户端连接数 |
接近 maxclients 需扩容 |
|
响应时间 |
单次操作耗时 |
> 1ms 需关注(正常 < 1ms) |
4.3 JVM 性能指标(Java 应用)
|
指标 |
说明 |
告警参考 |
|---|---|---|
|
堆内存使用率 |
已用堆内存 / 最大堆内存 |
> 80% 关注 |
|
GC 频率 |
每分钟 Full GC 次数 |
> 1 次/分钟 关注 |
|
GC 停顿时间 |
单次 GC 的 STW 时长 |
> 50ms 关注,> 200ms 告警 |
|
线程数 |
当前活跃线程数 |
突然暴增可能是线程泄漏 |
五、常用性能测试工具
5.1 工具对比
|
工具 |
类型 |
协议支持 |
脚本难度 |
分布式 |
适用场景 |
|---|---|---|---|---|---|
|
JMeter |
开源 GUI |
HTTP/HTTPS/TCP/JDBC等 |
中等 |
支持 |
通用 Web 压测 |
|
Gatling |
开源代码 |
HTTP/WebSocket/JMS |
较高 |
支持 |
持续集成场景 |
|
Locust |
开源 Python |
HTTP/自定义 |
较低 |
支持 |
Python 技术栈团队 |
|
wrk |
开源 CLI |
HTTP/HTTPS |
低 |
不支持 |
轻量快速压测 |
|
ab |
开源 CLI |
HTTP/HTTPS |
低 |
不支持 |
简单单机压测 |
|
K6 |
开源 JS |
HTTP/WebSocket/gRPC |
中等 |
支持(云) |
开发者友好 |
5.2 JMeter 使用指南
基本组件
|
组件 |
作用 |
|---|---|
|
Thread Group(线程组) |
模拟虚拟用户,设置并发数、循环次数 |
|
HTTP Request |
配置请求的 URL、方法、参数、Header |
|
CSV Data Set Config |
参数化,从 CSV 文件读取测试数据 |
|
Assertions(断言) |
验证响应结果是否符合预期 |
|
Listeners(监听器) |
收集和展示测试结果 |
|
Timer(定时器) |
控制请求间的间隔(模拟真实用户行为) |
关键监听器及指标
|
监听器 |
输出的关键指标 |
|---|---|
|
Summary Report |
Throughput、Avg/Min/Max RT、Error % |
|
Aggregate Report |
增加 P90、P95、P99 等分位数响应时间 |
|
View Results Tree |
查看单个请求的详细请求/响应数据 |
|
Backend Listener |
实时推送数据到 InfluxDB,配合 Grafana 可视化 |
JMeter 最佳实践
- 非 GUI 模式运行:
jmeter -n -t test.jmx -l result.jtl,GUI 模式消耗资源影响测试准确性 - 使用变量:
${__P(host, localhost)}通过命令行传参 - 合理设置 ramp-up:逐步增加负载,避免瞬间冲击
- 监控施压机资源:施压机本身不能成为瓶颈
5.3 监控体系搭建
JMeter/Gatling/Locust(施压工具)
│
▼
应用服务器 ──→ Prometheus / Telegraf(指标采集)
│
▼
InfluxDB / Prometheus(时序存储)
│
▼
Grafana(可视化仪表盘)──→ 告警通知
六、吞吐量-延迟曲线分析
6.1 关键判断点
- 线性增长区:吞吐量与并发量成正比,响应时间基本不变 → 系统正常
- 拐点(Knee Point):吞吐量增速放缓,响应时间开始明显增加 → 系统开始饱和
- 饱和区:吞吐量达到最大值后持平或下降,响应时间急剧增加 → 系统过载
- 崩溃区:错误率上升,吞吐量下降 → 系统即将崩溃
七、性能测试流程
7.1 标准流程
需求分析 → 测试计划 → 环境准备 → 脚本开发
│ │
└──── 结果分析 ← 执行测试 ← 数据准备 ←┘
7.2 各阶段要点
阶段一:需求分析 — 明确测试目标、确定 SLA、获取典型业务场景和流量模型
阶段二:测试计划 — 制定测试策略(先单接口后混合场景)、确定并发模型(梯度加压/恒定压力)、规划测试环境
阶段三:脚本开发 — 录制或编写测试脚本、参数化、添加断言、添加思考时间
阶段四:执行测试
- 基准测试(单用户单接口,了解基线性能)
- 负载测试(逐步加压到目标并发)
- 压力测试(继续加压找极限)
- 稳定性测试(目标并发长时间运行)
阶段五:结果分析 — 收集整理数据、分析性能瓶颈、与历史数据对比、输出测试报告
八、性能测试报告模板
一、测试概述
- 测试目的 / 测试范围 / 测试环境
二、测试场景
- 场景列表 / 并发模型 / 数据说明
三、测试结果
- 各项指标汇总表
- 吞吐-延迟曲线图
- 资源使用率趋势图
四、问题分析
- 发现的性能瓶颈 / 根因分析 / 优化建议
五、结论与建议
- 是否满足 SLA / 容量规划建议 / 后续优化方向
典型性能目标设定(参考)
|
指标 |
目标值 |
说明 |
|---|---|---|
|
QPS |
≥ 2000 req/s |
高并发处理能力 |
|
平均响应时间 |
≤ 150 ms |
大多数用户的感知体验 |
|
P95 响应时间 |
≤ 300 ms |
响应尾部控制 |
|
P99 响应时间 |
≤ 500 ms |
极端尾部控制 |
|
错误率 |
≤ 0.1% |
稳定性要求 |
|
CPU 使用率 |
≤ 70% |
避免临界过载 |
|
内存使用率 |
≤ 80% |
留出缓冲空间 |
|
GC 停顿时间 |
≤ 50 ms / 次 |
避免长停顿 |
|
数据库慢查询阈值 |
≤ 100 ms |
后端依赖性能保障 |
|
缓存命中率 |
≥ 95% |
保障缓存有效性 |
九、常见性能问题与优化策略
9.1 问题定位思路
|
现象 |
可能原因 |
排查方向 |
|---|---|---|
|
TPS 上不去 |
线程阻塞、连接池不够 |
线程 dump、连接池配置 |
|
响应时间随并发急剧增长 |
锁竞争、资源争抢 |
代码锁、数据库行锁 |
|
CPU 使用率高 |
计算密集、频繁 GC |
线程 dump 分析 CPU 热点 |
|
内存持续增长 |
内存泄漏 |
heap dump 分析 |
|
错误率突然增高 |
连接池耗尽、超时 |
超时配置、下游可用性 |
9.2 常见优化策略
代码层面: 减少对象创建、优化算法、异步处理(MQ 解耦)、合理使用连接池
数据库层面: 添加/优化索引、SQL 重写、读写分离、分库分表、连接池调优
缓存层面: 增加缓存层、热点预加载、缓存预热、合理过期策略(防雪崩/击穿/穿透)
架构层面: 服务拆分、负载均衡、CDN 加速、限流降级熔断、消息队列削峰填谷
十、性能测试常见误区
- 只看平均值:平均值掩盖了尾部延迟,P99 更能反映真实用户体验
- 忽略施压机瓶颈:施压机 CPU/内存/网络先到瓶颈,导致测试结果偏低
- 测试数据量太小:生产数据量级下的 SQL 执行计划可能完全不同
- 忽视预热:JIT 编译、缓存预热后的性能与冷启动差异显著
- 环境不一致:测试环境与生产环境配置差异过大导致结论无效
- 只测不分析:压出问题就结束,不深入定位和优化
- 忽略网络因素:测试环境与生产环境的网络延迟可能不同