Uvicorn本身不提供压测能力,需依赖wrk、locust或httpx等外部工具;常见错误包括网络隔离导致Connection refused、未关闭reload引发性能失真、workers数超核数反而降低性能。

Uvicorn本身不提供压测能力,得靠外部工具
Uvicorn是ASGI服务器,只负责接收和分发请求,不内置压测逻辑。想测它扛不扛得住,并发多少、延迟多高、哪里卡住,必须用专门的压测工具连它——就像不能让汽车引擎自己测试马力,得上测功机。
常见组合有三类:
-
wrk:轻量、高并发、Linux/macOS友好,Windows需WSL或Docker -
locust:行为建模强,适合模拟真实用户路径,但底层用同步requests,无法直接复用FastAPI的async client -
httpx + pytest-asyncio:代码级控制最细,适合单元化压测单个异步接口,但需手动管理连接池和并发调度
别指望uvicorn --workers 4启动完就自动压测——那只是开了4个进程,没发一个请求。
用wrk测Uvicorn时,端口和网络隔离最容易出错
本地启动Uvicorn后,默认绑定127.0.0.1:8000,而wrk在Docker里跑时,localhost指向容器内部,根本连不到宿主机的Uvicorn。现象是Connection refused,不是服务没起,是网络不通。
解决方法只有两个:
- 把Uvicorn绑定到
0.0.0.0:8000(uvicorn main:app --host 0.0.0.0 --port 8000),再用宿主机IP(如192.168.x.x)访问 - 在Docker中用
--network host模式运行wrk,让它共享宿主机网络栈
别试--add-host=host.docker.internal:host-gateway,Windows WSL下不一定生效;也别信“改hosts就能通”,Docker网络模型不认这个。
Uvicorn 0.52.1 是 Python ASGI Web 服务器,提供异步应用服务及 WebSocket 支持,常用于 FastAPI、Starlette 等应用的开发和部署。本下载为官方 PyPI 通用 wheel 包,可使用 pip 安装,并由包管理器处理所需依赖。
Locust压测FastAPI必须关掉reload和debug
Locust的HttpUser用的是同步requests库,而FastAPI开启--reload或debug=True时,会注入StatReload监听器和调试中间件,导致:
- 每个请求多花10–50ms在文件扫描上,压测结果严重失真
- 出现
RuntimeError: asyncio.run() cannot be called from a running event loop,尤其在Locust分布式worker模式下 - 日志里看到
INFO: Watching for file changes with StatReload,说明没关干净
正确启动命令是:
uvicorn main:app --host 0.0.0.0 --port 8000 --reload=False --workers 4 --log-level warning
同时确保代码里没写app = FastAPI(debug=True),环境变量也要设DEBUG=False。
workers数不是越多越好,超核数反而拖慢
Uvicorn多进程靠--workers N启动,但N设成8、16甚至32,不代表吞吐翻倍。实测中,超过CPU核心数 × 2后,上下文切换开销开始盖过并行收益,平均延迟反升。
更关键的是资源竞争:
- 数据库连接池若没配
max_connections,每个worker都抢连接,很快触发Too many clients - 全局缓存(比如用
dict存token)在各worker间不共享,缓存命中率暴跌 - 内存占用线性增长,4个worker可能吃掉单进程3倍内存
建议先用--workers 2压测基线,再逐步加到min(4, CPU核心数),观察P95延迟和错误率拐点——那里才是真实瓶颈所在。

















