最简可用Locust脚本需继承HttpUser、用@task装饰实例方法、通过self.client发请求并设host和headers;压测时应从小users/spawn-rate起步,关注RPS与响应时间曲线,结合服务端监控定位真实瓶颈。

Locust怎么写最简可用的并发脚本
Locust不是“写完就能压”,得先让 locustfile.py 跑起来且行为可控。核心是定义好 task 和 User 类,别一上来就堆逻辑。
- 用
HttpUser(不是旧版Locust)继承,否则self.client会报错 -
@task装饰器必须作用在实例方法上,写成@task(3)表示权重为3,不加括号默认权重1 - 请求路径别硬编码,用
self.client.get("/api/v1/users"),别用requests.get,否则 Locust 统计不到 - 如果要带 token 或 header,统一在
on_start里设self.client.headers,别每个请求都重复构造
示例最小可运行脚本:
from locust import HttpUser, task
class ApiUser(HttpUser):
host = "https://api.example.com"
def on_start(self):
self.client.headers = {"Authorization": "Bearer xyz"}
@task
def list_users(self):
self.client.get("/api/v1/users")
@task(2)
def get_profile(self):
self.client.get("/api/v1/profile")
压测时用户数和 spawn rate 怎么配才不翻车
很多人一开压测就设 1000 用户、每秒启 100,结果目标服务没崩,Locust 进程先 OOM 或 DNS 超时。关键不是“想压多少”,而是“能稳住多少”。
-
--users是总并发用户数,不是 QPS;实际 QPS 取决于任务耗时 + 用户数,比如单次请求平均 2s,100 用户 ≈ 50 QPS -
--spawn-rate控制每秒新增用户数,建议从 1–5 开始,观察 Locust Web UI 的 “Users” 曲线是否平滑上升;突增容易触发连接池打满或ConnectionRefusedError - 本地跑压测时,
--users超过 500 就可能受本机文件描述符限制,ulimit -n查看,默认常为 1024,不够就改 - 分布式模式下,
--master不发请求,只调度;--worker才真正发压,worker 数量 ≠ 并发数,别混淆
为什么响应时间对不上、错误率虚高
Locust 默认统计的是“从发请求到收到响应头”的时间,但业务真正卡住的地方往往在下游依赖(DB、Redis、第三方 API),而 Locust 不感知这些内部延迟。
立即学习“Python免费学习笔记(深入)”;
- 如果接口返回 200 但 JSON body 里有
"code": 500,Locust 默认当成功;需手动检查:with self.client.get(...) as response: if response.json().get("code") != 0: response.failure("business error") - 超时默认是 60 秒(
DEFAULT_TIMEOUT),长任务容易误判;可在HttpUser里设timeout = 10.0,或单次请求传timeout=5 - 重试机制默认关闭,遇到临时网络抖动会直接记为失败;如需自动重试,得自己封装
self.client.request加tenacity或简单 while 循环 - Web UI 的“Response Time”分位值(p95/p99)是全局聚合的,不代表单个用户真实体验;高尾延时可能被少数慢请求拉高,得结合日志查具体哪类请求拖后腿
怎么定位是代码慢还是服务慢
Locust 自身不是性能分析器,它只告诉你“这个请求花了多久”,但不说“花在哪”。真瓶颈常藏在 Python 层(比如序列化、循环拼接)、HTTP 客户端(连接复用失效)、或服务端中间件(日志采样、鉴权链路过长)。
- 在
task里加time.time()打点,对比self.client.get前后时间差,若差距大,说明慢在 Python 代码里(比如 JSON 解析、字段处理) - 用
self.client.get(..., name="raw_api")自定义事务名,避免多个路径被合并统计,方便区分真实接口和健康检查等干扰项 - 关掉 Locust 的
--headless,开 Web UI 实时看 “Charts” 页里的 RPS 和响应时间曲线:如果 RPS 上不去但用户数已满,大概率是服务端拒绝连接或限流了 - 别只信 Locust 报告——同时抓服务端
top、slowlog、APM(如 Sentry、Datadog)数据交叉验证;Python 服务本身 CPU 高,可能只是json.loads在解析巨量响应体
真正难的从来不是起多少并发,而是确认每一毫秒花得明明白白。尤其当 response.elapsed.total_seconds() 突然跳变,得立刻切到服务端日志和网络层看是不是 TLS 握手变慢、DNS 缓存失效,或者 Locust worker 本机时钟漂移了。











