locust压测rps上不去且cpu低,本质是工具未真正并发:需检查用户数、wait_time配置、master/worker版本一致性、本机连接数限制及服务端i/o模型、连接池、http客户端异步性等。

吞吐量低不是代码写得慢,而是请求根本没跑起来——多数情况是压测工具、网络或服务端配置卡在了“发不出去”或“接不住”的环节。
Locust 启动后 RPS 上不去,CPU 却很低
这是最典型的假性性能问题:压测工具没真正并发起来,服务器资源自然空转。
-
wait_time = between(1, 5)写成wait_time = constant(0.1)也不行——Locust 默认每用户串行执行任务,constant(0.1)表示“每个用户每 0.1 秒发一个请求”,但若只启了 10 个用户,理论最大 RPS 就是 10;要上量,必须提高user_count或改用constant_pacing - 忘记加
catch_response=True导致失败请求不计入统计,RPS 虚高但实际大量超时被静默丢弃 - Master/Worker 版本不一致(比如 Master 是
locust 2.15.1,Worker 是2.14.0),Worker 注册失败却不报错,看起来人很多,其实只有 Master 在单线程跑 - 压测机本机带宽或连接数打满:
netstat -an | grep :80 | wc -l超过 65535,说明本地端口耗尽,需调大net.ipv4.ip_local_port_range
Python 服务端响应快,但压测 QPS 卡在 200 左右
瓶颈不在业务逻辑,而在 I/O 模型和连接管理。
- 用
Flask + WSGI(如 gunicorn)默认是同步阻塞模型,workers=4+threads=2最多撑 8 并发,再多请求就排队等线程——换FastAPI + Uvicorn --workers 4 --http 1.1可轻松突破 3000+ QPS -
uvicorn启动时漏掉--limit-concurrency或--backlog,内核连接队列溢出,新连接被直接拒绝(看ss -s的failed计数) - 数据库连接池设得太小:比如
SQLAlchemy的pool_size=5,但压测开 100 用户,95% 请求在等连接——应设为并发用户的 1.5~2 倍,并确认max_overflow允许临时扩容 - HTTP 客户端(如调第三方 API)用了同步
requests,每个请求卡住整个协程——必须换成aiohttp或httpx.AsyncClient
内网压测 QPS 是外网 3 倍,且 CPU 利用率差 5 倍
这基本锁定是网络层问题,不是 Python 代码能调的。
- 外网 DNS 解析慢:
curl -w "%{time_namelookup}\n" -o /dev/null -s http://your-api.com查看是否 >100ms;压测时应直连 IP 或预填/etc/hosts - TCP 连接复用没打开:Locust 默认启用
keep-alive,但服务端 Nginx 或负载均衡器可能配了keepalive_timeout 5,连接刚建好就被关,反复握手拖垮吞吐 - SSL/TLS 握手耗时高:用
openssl s_time -connect your-api.com:443 -new测新建连接耗时;生产环境务必开启 TLS session resumption(ssl_session_cache shared:SSL:10m) - 运营商中间设备限速或 QoS 策略:对比同一台压测机分别走电信/联通线路的结果,差异大则基本可判定
压测中出现偶发长尾延迟(P99 > 1s),但平均 RT 很低
这类问题最容易被忽略,却直接拖垮吞吐上限——因为一个慢请求会阻塞整个连接或线程。
- 数据库慢查询未覆盖索引:哪怕 99% 请求走索引,剩下 1% 的
SELECT * FROM orders WHERE status = 'pending'没加索引,就会触发全表扫描,把连接池拖死 - 日志写入同步阻塞:比如用
logging.basicConfig直接写磁盘文件,在高并发下f.write()成为瓶颈;应切到异步 handler 或用concurrent.futures.ThreadPoolExecutor提交写日志任务 - Python GIL 下的 CPU 密集操作(如 JWT 验签、AES 解密)没做
asyncio.to_thread或concurrent.futures.ProcessPoolExecutor卸载,单个请求吃满一个核,其他协程全卡住 - Redis 连接未复用:每次请求都
redis.Redis()新建实例,TCP 连接反复创建销毁——必须用连接池(ConnectionPool)并全局复用 client
吞吐量不是算出来的,是压出来的;但压不出来时,先别翻业务代码——查连接、看网络、盯线程池,这三个地方占了八成以上的真实瓶颈。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











