单机支撑5000+ WebSocket连接的关键在于:防连接泄漏(用set管理+异常清理)、广播并发安全(asyncio.gather分批发送+心跳过滤)、杜绝同步阻塞(移除time.sleep/requests等,CPU密集操作进线程池)。

单机撑住 5000+ 活跃 WebSocket 连接,关键不在框架选型,而在三个地方是否做对:连接管理是否防泄漏、广播是否并发安全、同步调用是否被混入异步函数里。
async def websocket_endpoint() 里不能出现任何同步阻塞操作
常见错误现象是:连接数一过百,所有客户端开始卡顿、延迟飙升,websocket.receive_text() 响应变慢,甚至整个服务无响应。这不是 CPU 或带宽瓶颈,而是事件循环被某个同步操作锁死了。
-
time.sleep()、requests.get()、json.loads()(尤其解析 >1MB 的 JSON)必须移除或替换 - HTTP 调用改用
httpx.AsyncClient,数据库换asyncpg或aiomysql,别碰psycopg2和pymysql - CPU 密集型操作(如大 JSON 解析、AES 加密)必须进线程池:
await asyncio.to_thread(json.loads, data) - Pydantic 校验默认同步,高频场景建议关掉
validate_assignment=False,或直接用model_validate_json()避免重复解析
active_connections 用 list 就是内存泄漏定时炸弹
用 active_connections = [] 然后 .append(websocket) + for conn in active_connections: 发送消息,看似简单,实则危险。客户端异常断开(比如关浏览器、网络中断)时,websocket.send_text() 会抛出 WebSocketDisconnect 或 OSError,若没捕获,该连接对象就永远留在列表里 —— 内存持续上涨,几天后 OOM。
- 必须改用
set:self.active_connections: set[WebSocket] = set(),天然去重、增删快 - 每次广播前,对每个连接做
try/except,捕获WebSocketDisconnect和通用Exception,失败后立即connection_set.discard(ws) - 加心跳检测:在
while True:循环内定期await websocket.ping(),超时(比如 30 秒无响应)主动await websocket.close() - 生产环境务必监控:
psutil.Process().memory_info().rss定期打点,配合连接数趋势判断泄漏
广播消息不能 for-loop + await 逐个发
当有 2000 个连接时,for conn in conns: await conn.send_text(msg) 是串行执行,耗时线性增长;更糟的是,一个连接发送失败(比如网络抖动),后续所有连接都会被阻塞到异常处理完。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
立即学习“Python免费学习笔记(深入)”;
- 必须用
asyncio.gather(*tasks, return_exceptions=True)并发发送,例如:await asyncio.gather(*[conn.send_text(msg) for conn in conns], return_exceptions=True) - 连接数超 1000 时,建议分批(如每 200 个一组),避免一次性创建太多 task 压垮 event loop
- 广播前先过滤掉已失效连接(靠心跳或上次发送异常标记),减少无效调用
- 前端 Luckysheet 类协同场景,只广播 delta 操作(如
{"v": "new value", "r": 2, "c": 3}),而非整表 JSON,体积可降 90%
Uvicorn worker 数和并发限制必须手动配死
很多人照抄 gunicorn main:app -k uvicorn.workers.UvicornWorker -w 4 就上线,结果压测时 CPU 上下文切换飙升、文件描述符耗尽、内存翻倍 —— 因为 Uvicorn 是单线程异步模型,每个 worker 独占一个事件循环,盲目加 -w 反而降低吞吐。
- worker 数推荐:
CPU 核心数 × 1~1.5(例如 4 核机器设-w 4或-w 6) - 必须加
--limit-concurrency 100,防止单个 worker 接收过多连接压垮内存 - 启用
--ws-per-message-deflate开启 WebSocket 压缩,文本消息体积平均减少 40%+ - 生产环境禁用
--reload,它会 fork 多进程导致连接状态不同步、心跳失效、广播漏发
最易被忽略的点是:连接清理不是“发生异常才做”,而是要变成广播流程里的固定步骤;心跳不是“可选项”,而是连接生命周期管理的基础设施。没有这两条,其他优化都只是延缓崩溃时间。


















