fastapi websocket性能瓶颈主要在连接管理、消息广播和阻塞调用三处;需全程异步、用set管理连接并捕获异常、并发广播限流、合理配置uvicorn worker数及启用压缩。

FastAPI 的 WebSocket 性能瓶颈,90% 不出在协议本身,而出在连接管理、消息广播和阻塞调用这三处。只要避开这几个坑,单机轻松撑住 5000+ 活跃连接。
async def websocket_endpoint() 必须全程异步,不能混入同步调用
常见错误是:在 websocket.receive_text() 或 websocket.send_text() 之间插入 time.sleep()、requests.get()、json.loads()(大对象)、或未加 await 的数据库查询。这些操作会卡死整个事件循环,所有连接都变卡顿。
- 耗时 IO 操作必须用异步替代:用
httpx.AsyncClient替代requests,用aiomysql/asyncpg替代pymysql/psycopg2 - CPU 密集型操作(如大 JSON 解析、加密)要丢进线程池:
await asyncio.to_thread(json.loads, data) - Pydantic 模型校验默认是同步的,高频场景下建议关掉验证或用
model_validate_json()避免重复解析
全局 list 存 active_connections 是内存泄漏高发区
用 active_connections = [] 追加连接再遍历发送,看似简单,但一旦客户端异常断开(比如关浏览器、网络中断),websocket.send_text() 会抛异常,而代码没捕获 → 连接永远留在列表里 → 内存持续上涨 → OOM。
- 改用
set而非list,避免重复添加 - 每次广播前必须做
try/except捕获WebSocketDisconnect和通用Exception,把失效连接从集合中移除 - 加心跳检测:在
while True:循环里定期await websocket.ping(),超时则主动close() - 生产环境务必加连接数监控,比如用
psutil.Process().memory_info().rss定期打点
Gunicorn + Uvicorn worker 数不是越多越好
gunicorn main:app -k uvicorn.workers.UvicornWorker -w 4 是常见配置,但盲目加 -w 反而降低性能 —— Uvicorn 本身是单线程异步,每个 worker 独占一个事件循环;过多 worker 会导致 CPU 上下文切换激增、内存冗余、甚至文件描述符耗尽。
- 推荐值:worker 数 = CPU 核心数 × 1~1.5(例如 4 核机器设
-w 4或-w 6) - 必须配
--limit-concurrency 100防止单个 worker 接收过多连接压垮内存 - 启用
--ws-per-message-deflate开启 WebSocket 压缩,对文本消息可减小 40%+ 传输体积 - 禁用
--reload(开发用),生产必须关 —— 它会 fork 多个进程导致连接状态不同步
广播消息不能 for-loop + await 逐个发
当有 2000 个连接时,for conn in connections: await conn.send_text(...) 是串行的,哪怕每个 send 耗时 2ms,一轮也要 4 秒 —— 用户感知就是“卡”。
- 改用
asyncio.gather(*[conn.send_text(...) for conn in connections], return_exceptions=True)并发发送 - 注意:
gather会同时触发所有 send,可能触发内核缓冲区溢出,需配合asyncio.Semaphore(100)限流 - 更稳的做法是把消息推到
asyncio.Queue,由后台任务消费并分批广播,解耦接收与发送节奏 - 纯通知类消息(如“用户上线”)可考虑只发给相关房间,而非全量广播
真正难的不是写 async,而是判断哪一步该 await、哪一步该丢进线程池、哪一步该进队列 —— 这些边界不靠文档,得靠 print(time.time()) 和 psutil 实测出来。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











