用 AI 设计压测场景:基准、负载、压力、稳定性与尖峰
「压到 5000 并发」不是一个场景,它只是一次没有对照的表演。压测跑不出结论,多半是场景没定义清楚:回答什么问题、用哪条加压曲线、跑多久、什么算通过,这四件事必须写在动手之前。让 AI 介入的正确位置,是先让它产出场景表,再让它把表翻译成脚本。
一、五类场景的定义
| 场景 | 回答的问题 | 加压曲线 | 时长 | 通过标准 |
|---|---|---|---|---|
| 基准(Benchmark) | 单个请求有多快,版本之间有没有退化 | 恒定低并发(1~10),不爬坡 | 1~3 分钟 | P99 波动 < 10%,与上次基线差 < 5% |
| 负载(Load) | 设计容量下能否达标 | 阶梯爬到目标后保持 | 10~30 分钟 | 目标 QPS 达成、P99 达标、错误率 < 0.1% |
| 压力(Stress) | 上限在哪里,越界后怎么坏 | 持续阶梯加,每档 2~5 分钟 | 30~60 分钟 | 找到拐点,破线后必须有恢复段观察回落 |
| 稳定性(Soak) | 内存、fd、连接池会不会累积上涨 | 恒定在负载的 60%~70% | 2~12 小时 | 内存斜率趋近 0,错误率无随时间上升趋势 |
| 尖峰(Spike) | 突发流量能否扛住并自动恢复 | 秒级从基线跳到 3 | 10~20 分钟 | 尖峰内错误率 < 1%,回落 5 分钟内回到基线 |
顺序也有讲究:基准 → 负载 → 压力 → 稳定性 → 尖峰。跳过基准直接做负载,后面所有的数字都没有参照物;跳过压力直接做稳定性,你不知道自己维持的是 60% 还是 95% 容量。
二、提示词:要场景表,不要脚本
角色:性能测试场景设计者,先输出表格,不要写脚本。
被测系统:订单查询服务,HTTP/1.1,接口 GET /api/v1/order/{id},鉴权用 Bearer token。
容量线索:单实例 4C8G,当前线上峰值 800 QPS,P99 约 60ms。
目标:找出单实例安全容量并给出上线余量建议。
要求:
1) 输出场景表,列固定为:场景名 | 并发 | 目标 QPS | 时长 | 加压曲线 | 通过标准 | 观测项
2) 五类场景(基准/负载/压力/稳定性/尖峰)每类至少一行,参数必须具体到数字
3) 明确每一行「为什么是这个数字」,用一句话说明推算依据
4) 指出哪些参数需要先做小规模试压才能定,不要给编造的依据
5) 最后给出执行顺序与每类场景之间的间隔要求(环境复位、缓存清理、等待稳定)
要求「参数具体到数字」和「说明推算依据」这两条,能把大部分「并发 1000、时长 10 分钟」式的敷衍输出挡掉。
三、它应该产出的场景表
| 场景名 | 并发 | 目标 QPS | 时长 | 加压曲线 | 观测项 |
|---|---|---|---|---|---|
| 基准-单接口 | 1 | 1 | 2 分钟 | 恒定,无爬坡 | P50/P99、响应体大小、CPU |
| 基准-版本对照 | 1 | 1 | 2 分钟 ×2 | 恒定,新旧版本各一次 | P99 差值、GC 次数 |
| 负载-设计容量 | 50 | 800 | 20 分钟 | 爬坡 2 分钟后保持 | QPS、P99、错误率、连接池占用 |
| 负载-带缓存混合 | 80 | 1200 | 20 分钟 | 爬坡 5 分钟后保持 | 缓存命中率、下游 QPS |
| 压力-找拐点 | 阶梯 20→400 | 不限速 | 40 分钟 | 每 5 分钟翻一档,共 8 档 | P99 拐点、CPU、队列长度、GC 暂停 |
| 压力-恢复段 | 0 | 0 | 5 分钟 | 直接降为 0 | fd、连接池、内存是否回落到基线 |
| 稳定性-长跑 | 30 | 500 | 8 小时 | 爬坡后恒定在 60% 容量 | 内存斜率、fd 增长、错误率趋势 |
| 尖峰-秒杀式 | 10→500 | 80→4000 | 15 分钟 | 30 秒内跳到 5 倍,维持 2 分钟后回落 | 峰值错误率、超时数、恢复时间 |
这张表的每一行都能直接翻译成一段 k6 配置,这也是要求 AI「先出表」的价值:表格里的错误比脚本里的错误便宜得多。
四、把场景表翻译成加压曲线
// bench/scenarios.js:五类场景共用一份脚本,靠 SCENARIO 环境变量切换
import http from 'k6/http';
import { check } from 'k6';
const shapes = {
// 基准:恒定单并发,只为拿可对比的基线数字
benchmark: [{ duration: '2m', target: 1 }],
// 负载:爬坡 2 分钟后长时间保持,观察稳态
load: [
{ duration: '2m', target: 50 },
{ duration: '18m', target: 50 },
],
// 压力:每 5 分钟翻一档,直到指标破线,末尾留恢复段
stress: [
{ duration: '5m', target: 20 },
{ duration: '5m', target: 40 },
{ duration: '5m', target: 80 },
{ duration: '5m', target: 160 },
{ duration: '5m', target: 320 },
{ duration: '5m', target: 0 },
],
// 尖峰:30 秒内跳到 5 倍并维持 2 分钟,再快速回落
spike: [
{ duration: '2m', target: 10 },
{ duration: '30s', target: 500 },
{ duration: '2m', target: 500 },
{ duration: '30s', target: 10 },
{ duration: '5m', target: 10 },
],
// 稳定性:爬坡后恒定长跑,重点看累积曲线而不是峰值
soak: [
{ duration: '2m', target: 30 },
{ duration: '8h', target: 30 },
],
};
export const options = {
scenarios: {
run: {
executor: 'ramping-vus',
stages: shapes[__ENV.SCENARIO || 'load'],
gracefulStop: '30s', // 留出在途请求收尾时间,否则错误率虚高
},
},
thresholds: {
http_req_failed: ['rate<0.001'],
http_req_duration: ['p(99)<100'],
},
};
export default function () {
const res = http.get(`${__ENV.BASE}/api/v1/order/1001`, {
headers: { Authorization: `Bearer ${__ENV.TOKEN}` },
});
check(res, { 'status is 200': (r) => r.status === 200 });
}
for s in benchmark load stress spike soak; do
k6 run -e SCENARIO=$s -e BASE=http://10.0.0.12:8080 -e TOKEN="$T" \
--summary-export="summary-$s.json" bench/scenarios.js
sleep 300 # 场景之间留复位时间:清缓存、等连接池回落、确认 fd 回到基线
done
压力场景的 stages 是并发曲线而不是 QPS 曲线:并发翻倍、QPS 不涨,就是拐点所在;想固定 QPS 做压力测试,把执行器换成 ramping-arrival-rate,用 rate 描述到达率。
五、通过标准要写进阈值,而不是写在文档里
| 场景 | 阈值写法 | 备注 |
|---|---|---|
| 基准 | http_req_duration: ['p(99)<80'] | 基线本身要存档,用于跨版本比对 |
| 负载 | p(99)<100 + http_req_failed: ['rate<0.001'] | 达标即可,不追求极限 |
| 压力 | 不设阈值,改为人工判读拐点 | 阈值会让脚本提前中断,反而不利于找上限 |
| 稳定性 | p(99)<150 + 内存增长趋势人工判读 | 阈值只兜住明显劣化,长跑看斜率 |
| 尖峰 | http_req_failed: ['rate<0.01'] | 尖峰内放宽到 1%,但恢复时间必须单独记录 |
常见坑
| 坑 | 现象 | 做法 |
|---|---|---|
| 没有基准就做负载 | 数字无参照,无法判断好坏 | 每类压测前先跑一次 2 分钟基准 |
| 场景之间不复位 | 上一轮缓存、连接池、GC 状态污染下一轮 | 场景间隔 5 分钟,必要时重启服务 |
| 稳定性只跑 30 分钟 | 累积型问题(fd、内存泄漏)看不出来 | 至少 2 小时,长连接类建议 8 小时以上 |
| 尖峰没有回落段 | 无法判断是硬扛还是缓慢劣化 | 峰后必须保留 5 分钟基线观察窗口 |
| 压力场景设了阈值 | 脚本在拐点前中断,拿不到上限 | 压力场景关闭阈值,靠人工判读 |
| 所有场景共用一份数据 | 缓存命中率虚高,压的是缓存不是服务 | 按场景准备不同位点与热度的数据 |
| 只记录峰值数字 | 丢掉了曲线和拐点 | 导出原始数据,把 QPS、延迟、资源画在同一时间轴 |
小结:五类场景各自回答一个不同的问题——基准给参照、负载验容量、压力找上限、稳定性看累积、尖峰测恢复;让 AI 先输出固定列(场景名 / 并发 / 目标 QPS / 时长 / 加压曲线 / 通过标准 / 观测项)的场景表,要求参数具体到数字并说明推算依据,再把表翻译成 stages;执行顺序固定为基准在前、压力居中、稳定性与尖峰在后,每轮之间留复位时间,通过标准尽量写成阈值,压力场景则留给人工判读。长连接与 IM 场景的具体参数可对照 im-ws 目录第 18 章与 im-system 目录第 26 章。