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 压测流程概述

一个标准化的性能压测流程通常包含以下六个阶段:

  1. 需求分析:明确压测目标(如“支持 1000 并发用户,P95 RT < 500ms”),确定关键业务场景与数据规模。
  2. 脚本开发:使用压测工具(如 k6)编写模拟用户行为的脚本,包括登录、浏览、下单等业务操作。
  3. 环境准备:搭建与生产环境配置相近的压测环境,准备测试数据,确保网络、监控、日志等基础设施就绪。
  4. 执行压测:按预设的并发梯度逐步加压,从低负载到目标负载,观察系统各项指标变化。
  5. 监控与采集:实时收集 TPS、RT、P95/P99、CPU、内存、GC、数据库连接数等数据。
  6. 分析与调优:对比指标与阈值,定位瓶颈,进行代码、配置或架构层面的优化,然后回归验证。

下图展示了压测流程中各阶段之间的迭代关系:

性能压测流程迭代图 性能压测标准流程(迭代模型) 需求分析 脚本开发 环境准备 执行压测 监控采集 分析调优 调优后回归 说明:虚线箭头表示“分析调优”后可能返回“环境准备”或“脚本开发”阶段进行迭代,直至满足阈值目标。

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 延迟是否达标。如果未达标,则说明当前水位已超过阈值,需要进一步分析瓶颈。

1.5 本章小结