1. 性能压测基础:定义、目的、指标与流程
1.1 性能压测的定义与目的
性能压测(Performance & Stress Testing)是通过模拟真实用户或业务场景,对系统施加预期或超预期的并发负载,以测量系统响应速度、吞吐量、资源消耗和稳定性的一种测试活动。其核心目的包括:
- 验证容量规划:确认系统能否支撑目标并发用户数与业务量。
- 发现性能瓶颈:定位数据库、中间件、网络、代码逻辑等环节的短板。
- 评估系统稳定性:在持续高压下检验是否存在内存泄漏、连接池耗尽、CPU 毛刺等问题。
- 校准服务等级协议(SLA):为 P95/P99 延迟、错误率等关键指标设定可量化的阈值。
- 辅助容量伸缩决策:为弹性伸缩策略、硬件扩容或架构优化提供数据依据。
提示: 压测不是一次性的“通过/不通过”检查,而是一个持续校准的过程。在《k6 压测水位 P95 阈值校准》课程中,我们将重点围绕 P95 延迟的“水位线”进行动态调整与验证。
1.2 常见性能指标
性能压测涉及多个量化指标,下表列出了最核心的几项及其含义:
| 指标 | 全称 | 定义 | 典型关注点 |
|---|---|---|---|
| TPS | Transactions Per Second | 系统每秒处理的事务数(通常指完整业务操作) | 业务吞吐能力 |
| QPS | Queries Per Second | 系统每秒处理的查询或请求数(常用于接口/数据库层) | 接口并发处理能力 |
| RT | Response Time | 从发送请求到收到完整响应所经过的时间(单位:ms) | 用户体验 |
| P95 | 95th Percentile | 将 RT 从小到大排序,排在第 95% 位置的值 | 绝大多数用户的体验上限 |
| P99 | 99th Percentile | 将 RT 从小到大排序,排在第 99% 位置的值 | 长尾延迟、极端情况 |
| 错误率 | Error Rate | 失败请求数占总请求数的百分比 | 系统可靠性 |
关键区别: TPS 强调完整业务事务(如一次下单包含查询库存、扣减余额、生成订单等多个步骤),QPS 更侧重单次请求/查询。在微服务架构中,一个 TPS 可能对应多个 QPS。
1.3 压测流程概述
一个标准化的性能压测流程通常包含以下六个阶段:
- 需求分析:明确压测目标(如“支持 1000 并发用户,P95 RT < 500ms”),确定关键业务场景与数据规模。
- 脚本开发:使用压测工具(如 k6)编写模拟用户行为的脚本,包括登录、浏览、下单等业务操作。
- 环境准备:搭建与生产环境配置相近的压测环境,准备测试数据,确保网络、监控、日志等基础设施就绪。
- 执行压测:按预设的并发梯度逐步加压,从低负载到目标负载,观察系统各项指标变化。
- 监控与采集:实时收集 TPS、RT、P95/P99、CPU、内存、GC、数据库连接数等数据。
- 分析与调优:对比指标与阈值,定位瓶颈,进行代码、配置或架构层面的优化,然后回归验证。
下图展示了压测流程中各阶段之间的迭代关系:
1.4 压测水位与 P95 阈值校准
在压测实践中,“水位”(Water Level)指系统在不同并发压力下表现出的性能拐点。P95 阈值校准的核心思路是:
- 设定一个可接受的 P95 延迟上限(例如 500ms)。
- 逐步增加并发虚拟用户数(VUs),观察 P95 延迟的变化曲线。
- 当 P95 延迟接近或超过阈值时,记录此时的并发数作为“安全水位”。
- 根据安全水位与实际业务峰值,决定是否需要扩容或优化。
注意: 不要只关注平均 RT。平均 RT 会掩盖长尾问题,P95/P99 才是衡量用户体验的关键。在 k6 中,可以通过内置的
trend 指标轻松计算百分位值。
以下是一个简单的 k6 脚本片段,演示如何定义 P95 阈值并在压测中检查:
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Trend } from 'k6/metrics';
// 自定义趋势指标,用于计算 P95
const myTrend = new Trend('api_response_time');
export const options = {
vus: 50,
duration: '30s',
thresholds: {
// 设定 P95 阈值:95% 的请求响应时间必须小于 500ms
'api_response_time': ['p(95)<500'],
},
};
export default function () {
const res = http.get('https://test-api.example.com/endpoint');
myTrend.add(res.timings.duration);
check(res, { 'status is 200': (r) => r.status === 200 });
sleep(1);
}
上述脚本中,thresholds 配置了 p(95)<500,当压测结束时,k6 会自动报告 P95 延迟是否达标。如果未达标,则说明当前水位已超过阈值,需要进一步分析瓶颈。