压测最常见的翻车不是脚本写不出来,而是"结论没法复现"——同一脚本今天 P99 800ms 明天 P99 2s,谁也说不清是系统变了还是测试本身的问题。这篇讲用 Locust 做压测时,如何把"脚本"升级成"可复现的实验"。
一、脚本设计:用户模型,不是请求列表
Locust 的 HttpUser 是"一个真实用户的行为模型",不是接口调用清单:
1 | class ChatUser(HttpUser): |
要点:
- 权重比就是流量模型:开会话 : 发消息 : 搜索 = 3:1:1,这个数字应该来自线上 access log 的统计,不是拍脑袋;
wait_time用分布而不是固定值:between(2,8)模拟人类节奏,固定 3s 会让 QPS 曲线出现假性规律;on_start里的登录不要放进@task——登录只该发生一次,否则登录接口 QPS 被虚高 10 倍。
二、压测曲线:阶梯式,不要一上来满负载
"直接上 500 并发看崩溃"得不到任何有用结论。阶梯曲线每一级回答一个问题:
1 | # locustfile 外部控制(locust -f locustfile.py --headless 不适用曲线控制, |
每级阶梯记录:平均 RT / P95 / P99 / 错误率 / 依赖侧 CPU。判读规则:
- P99 开始非线性上涨的那一级 = 拐点,拐点并发数就是容量的工作值;
- 错误率在拐点前就出现(如 504)= 依赖先于自身瓶颈(DB 连接池、下游限流),去查依赖;
- 每级之间留 30s 的"稳定窗口"再采样,爬坡期的数据不要进结论。
三、复现性:压测报告必须附"实验元数据"
这是"结论没法复现"的直接解药——每次压测落一份元数据:
1 | run_id: perf-20240615-02 |
三条纪律:
- 被测系统必须锁定 git sha——"staging 环境"不是版本,版本是 sha;
- 数据池预生成:测试账号、会话、商品数据在压测前准备好(和 2026 年那篇"数据工厂"衔接),压测中现造数据会把 DB 写入延迟混进结论;
- 同机压测要声明:压测机与被测机同机房/同网段时,结论只对该网络条件成立,元数据里写明拓扑。
四、常见误读
| 现象 | 常见误读 | 实际可能 |
|---|---|---|
| 高并发下 P99 暴涨、P50 正常 | 应用慢 | 连接池耗尽后的排队(看依赖侧等待时间拆分) |
| 错误率 0.1% 集中在某接口 | 接口偶发 bug | 该接口超时阈值 < 其 P99(阈值和真实分布不匹配) |
| 阶梯每一级 P95 都涨 20% | 线性劣化 | 正常——RT 随并发上升是必然,斜率突变才是信号 |
| 压测机 CPU 100% | 系统到瓶颈了 | 压测机先饱和,被测系统还没到(查 locust 进程 CPU) |
五、小结
Locust 只是"发压的枪",压测的含金量在流量模型(权重+节奏)、曲线设计(阶梯+稳定窗)、实验元数据(sha+数据池+拓扑)。做到这三点,压测报告才是可复现的实验记录,而不是"看起来很快"的截图。