发布于2026-07-20 阅读(0)
扫一扫,手机访问
说句大实话,FastAPI的WebSocket性能瓶颈,90%都不在协议本身,而是卡在连接管理、消息广播和阻塞调用这三件事上。只要把这几块处理好了,单机轻松撑住5000+活跃连接,真不是什么难事。
最容易踩的坑,就是在 websocket.receive_text() 或 websocket.send_text() 之间插入了同步操作。比如 time.sleep()、requests.get()、对大对象做 json.loads(),或者没加 await 的数据库查询。这些操作会直接卡死事件循环,结果就是所有连接都跟着变卡顿,一个拖慢一片。
httpx.AsyncClient 替换 requests,用 aiomysql 或 asyncpg 替换 pymysql 或 psycopg2await asyncio.to_thread(json.loads, data)model_validate_json() 来避免重复解析很多人图省事,直接用 active_connections = [] 来追加连接、遍历发送。表面上看挺简单,但一旦客户端异常断开——比如关浏览器、网络中断——websocket.send_text() 会抛异常。如果代码没捕获这个异常,这个连接就永远留在列表里,内存持续上涨,最后导致OOM。
set 而不是 list,避免重复添加try/except 捕获 WebSocketDisconnect 和通用 Exception,把失效连接从集合中移除while True: 循环里定期 await websocket.ping(),超时了主动 close()psutil.Process().memory_info().rss 定期打点gunicorn main:app -k uvicorn.workers.UvicornWorker -w 4 是常见配置,但盲目增加 -w 往往适得其反。Uvicorn 本身是单线程异步模型,每个 worker 独占一个事件循环;worker 过多会导致 CPU 上下文切换激增、内存冗余,甚至文件描述符耗尽。
-w 4 或 -w 6--limit-concurrency 100,防止单个 worker 接收过多连接压垮内存--ws-per-message-deflate 开启 WebSocket 压缩,对文本消息可减小40%以上的传输体积--reload(仅开发用),生产环境必须关掉——它会 fork 出多个进程,导致连接状态不同步想象一下,当有2000个连接在线时,如果写 for conn in connections: await conn.send_text(...),这就是串行发送。哪怕每个 send 只耗时2毫秒,一轮也要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 实测,才能找到最合适的方案。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8