直播电商项目提出大促性能需求:“帮我测到 10 万并发,接口 P95 不超过 500ms。”
这句话无法直接写压测脚本。10 万人是 30 秒内同时点“抢购”,还是 2 小时在线浏览?他们是否集中购买一个爆品?支付链路是否真实?超过容量后允许排队、限流,还是必须全部成功?不把这些问题说清,测出来的 10 万只是一个仪表盘数字。

并发数不是流量入口,而是系统里的在途结果
同样每秒进入 1000 个请求,平均响应 100ms 时大约有 100 个在途;响应恶化到 3 秒,在途会膨胀到约 3000。若压测工具采用“一个用户等响应回来再发下一个”的关闭模型,系统越慢,工具发得反而越少,会掩盖最危险的排队阶段。
直播开售更适合按外部到达率还原:预热阶段逐步增长,主播口令后 30 秒形成尖峰,随后回落。浏览、领券、下单、查询和支付按真实比例混合,而不是只压一个最轻的 GET 接口。

把“10 万人”编译成负载模型
假设 10 万用户在 30 秒内涌入,70% 浏览商品、18% 领取资格、8% 创建订单、4% 查询结果。热点爆品承接 65% 下单,其他商品分散。可以先写成开放到达模型:
export const options = {
scenarios: {
browse: {
executor: 'ramping-arrival-rate',
startRate: 300,
timeUnit: '1s',
preAllocatedVUs: 1200,
stages: [
{
target: 2400, duration: '20s' },
{
target: 2400, duration: '30s' },
{
target: 600, duration: '40s' }
]
}
},
thresholds: {
http_req_failed: ['rate<0.01'],
http_req_duration: ['p(95)<500', 'p(99)<1200']
}
};
代码里的速率只是示例,真实数值要从活动预测与历史流量推导。还要为下单、支付使用不同函数和权重,按业务键制造热点;否则一万商品均匀访问会把缓存和数据库锁竞争“洗平”。
压测分五段,才能找到容量拐点
第一段做单请求基线,排除脚本和环境问题;第二段逐步加压,观察延迟何时偏离线性;第三段在目标容量稳定运行,检查内存和队列是否持续积累;第四段超过目标寻找拐点与降级行为;第五段停止高压,验证系统是否在规定时间恢复。
不要只记录 CPU。至少联动客户端等待、网关排队、线程池、连接池、缓存命中、数据库锁、下游耗时、消息积压和业务成功数。某个服务 CPU 只有 50%,连接池已经耗尽,系统一样会崩。
性能报告必须能对业务账
请求成功不代表抢购正确。下单数不能超过可售库存;同一用户不能重复占资格;支付成功必须有订单;被限流用户要收到明确结果;超时后查询能找到最终状态。
def assert_sale_reconciliation(report, repository, stock):
paid = repository.count_orders(status="PAID")
reserved = repository.count_orders(status="RESERVED")
unique_buyers = repository.count_unique_buyers()
assert paid + reserved <= stock
assert report["accepted_orders"] == paid + reserved
assert unique_buyers == paid + reserved
assert report["unknown_outcomes"] == 0
如果业务允许一人多单,最后一条需按实际规则调整。关键是让性能测试同时验证速度与正确性,不把数据库里悄悄错掉的订单当成吞吐成绩。

最终要交付的是容量账和退让方案
报告应给出安全容量,而不是极限截图:在既定业务混合下,满足 SLO 且资源留有余量的到达率;扩容需要提前多久;排队到什么长度触发限流;哪些用户或业务优先;故障后多久恢复;目标高峰超过安全容量时需要削减什么。
高级性能课程适合团队补齐建模、诊断与容量规划能力;对于大促、核心交易或复杂微服务,也可以采用企业内训或性能专项外包共同完成业务建模、脚本、观测和演练。无论采用哪种方式,验收都不应停留在“工具打出了多少并发”。
性能测试真正回答的不是系统能不能扛住 10 万,而是用户以什么方式到来时,系统在哪个点开始失控、怎样有序退让、恢复后业务账是否仍然正确。