Locust专为负载测试设计,能真实模拟用户行为并统计关键指标;需为每个HttpUser实例独立管理session、token和host,用task装饰器按权重分配流量。

用 locust 而不是手写 requests 循环做压测
自己用 threading 或 asyncio 拼并发请求,看似灵活,实则难以模拟真实用户行为(比如思考时间、会话保持、失败重试),也很难统计吞吐量、响应分布、错误率等关键指标。Locust 是专为负载测试设计的框架,底层基于 gevent,能轻松支撑数千并发用户,且脚本即代码、无需额外配置文件。
常见错误是把 Locust 当成“高级 requests”,只写 self.client.get() 就完事——这会导致所有用户共用一个 TCP 连接池、Cookie 不隔离、无法体现登录态流失等问题。
- 每个
HttpUser实例天然拥有独立的self.client,自动管理 session 和连接复用 - 必须在
on_start()中完成登录并保存 token 到self.token,后续请求通过headers={'Authorization': f'Bearer {self.token}'}透传 - 避免在
tasks中硬编码 URL;用self.host = 'https://api.example.com'统一管理基地址,便于切换环境
定义多接口任务时,用 task 装饰器控制权重
真实业务中,不同接口调用频次差异很大:比如「获取用户信息」可能占 60% 流量,「提交订单」只占 5%。Locust 默认按函数定义顺序轮询,不加干预会导致流量分配失真。
错误做法是写一堆 if random() —— 逻辑混杂、不可维护、权重难校准。
立即学习“Python免费学习笔记(深入)”;
- 给每个接口方法加上
@task(6)、@task(1)这样的整数权重,Locust 会按比例分发请求(如 6:1 表示 profile 接口被调用概率是 submit 的 6 倍) - 权重值本身无单位,只看相对大小;支持小数如
@task(0.5),但建议统一用整数避免歧义 - 若某接口需带路径参数(如
/users/<code>user_id),应在on_start()预生成 ID 列表存入self.user_ids,任务中用random.choice(self.user_ids)取值,避免所有用户刷同一个 ID
运行时区分环境与资源限制,别直接跑 locust -f script.py
本地开发机跑压测,常因 CPU/内存不足或端口冲突导致结果失真,甚至把测试目标服务打挂而没意识到是自己机器扛不住。
典型错误包括:用默认 --users 1000 在笔记本上硬刚;忽略 --spawn-rate 导致瞬间洪峰击穿目标;忘记加 --headless 在 CI 中卡住进程。
- 始终显式指定
--users(总并发数)和--spawn-rate(每秒启动用户数),例如locust -f test_api.py --users 200 --spawn-rate 10 --headless --run-time 5m - 生产环境压测前,先在同网段跳板机运行,避免办公网出口带宽成为瓶颈
- 通过
--host https://staging-api.example.com切换目标地址,而非改 Python 文件里的host字段——后者容易误提交到主干
结果里重点关注 Response time 95%ile 和 Failures 列
很多人只扫一眼 Requests/s 就下结论,但这个数字掩盖了长尾延迟。比如平均响应 200ms,但 95%ile 是 2s,说明大量用户实际体验极差。
另一个盲区是忽略 Failures 的具体错误类型:ConnectionError 通常指向网络或目标服务崩溃;429 Too Many Requests 是限流触发;而 502 Bad Gateway 往往暴露了网关层配置缺陷。
- 压测中实时观察 Web UI 的
Charts标签页,重点拖动时间轴看Response time波动是否伴随Failures爆增 - 结束后导出
stats_history.csv,用 Excel 看Median Response Time和95% Line的差值——若超过 3 倍,说明响应时间分布严重偏斜 - 如果
failures里出现大量ReadTimeout,优先检查 locust 主机到目标服务的网络延迟(ping+mtr),而不是立刻优化后端代码
真正难的是让压测流量逼近真实用户行为:比如混合读写比例、模拟 JWT 过期重刷、处理 302 跳转、按设备 UA 分流。这些细节不写进脚本,再高的并发数也只是虚假繁荣。


















