FastAPI WebSocket消息接收异常排查与最佳实践咨询
代码存在的问题及修复
核心问题
当前的WebSocket端点仅会把收到的消息回发给发送该消息的客户端,完全没有实现跨客户端的消息转发逻辑。当/send页面发送消息时,后端只把消息原路返回给/send的WebSocket连接,/receive页面的连接根本收不到任何消息。
修复方案
需要在后端维护一个活跃连接池,保存所有已建立的WebSocket连接,收到消息后遍历所有连接完成广播:
修改后的完整代码:
from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse from fastapi.websockets import WebSocket from typing import List app = FastAPI() # 存储所有活跃的WebSocket连接 active_connections: List[WebSocket] = [] async def add_connection(websocket: WebSocket): await websocket.accept() active_connections.append(websocket) async def remove_connection(websocket: WebSocket): active_connections.remove(websocket) async def broadcast_message(message: str): # 遍历所有连接,发送消息 for conn in active_connections: await conn.send_text(message) @app.get("/send") def send_page(): return HTMLResponse(content=""" <html> <head> <title>发送消息</title> </head> <body> <h1>消息发送页</h1> <button id="send-button">发送广播消息</button> <script> const socket = new WebSocket("ws://localhost:8000/ws"); socket.onopen = () => console.log("连接成功"); document.getElementById("send-button").addEventListener("click", () => { socket.send("仪表盘更新数据:当前温度25℃"); }); </script> </body> </html> """) @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await add_connection(websocket) try: while True: message = await websocket.receive_text() print(f"收到客户端消息:{message}") # 广播消息给所有在线客户端 await broadcast_message(message) except Exception as e: print(f"连接异常断开:{str(e)}") finally: await remove_connection(websocket) @app.get("/receive") def receive_page(): return HTMLResponse(content=""" <html> <head> <title>接收消息(仪表盘)</title> </head> <body> <h1 id="display">当前数据:无</h1> <script> const socket = new WebSocket("ws://localhost:8000/ws"); socket.onopen = () => console.log("连接成功"); socket.onmessage = (event) => { document.getElementById("display").innerText = event.data; }; socket.onerror = (err) => console.log("连接出错:", err); </script> </body> </html>""")
可用的WebSocket前端库
如果不想用原生JavaScript,这些封装库能简化开发流程:
- Socket.IO:内置WebSocket+降级兼容(长轮询等),自带房间、广播、重连机制,适合复杂实时场景
- SockJS:跨浏览器的WebSocket兼容层,解决部分环境下WebSocket被禁用的问题
- ReconnectingWebSocket:原生WebSocket的轻量封装,自动处理断连重连,适合需要稳定连接的场景
WebSocket处理最佳方案
- 连接生命周期管理:必须维护连接池,处理连接的添加、移除,同时通过
try/finally保证异常断开时连接能被正确清理 - 结构化消息:不要直接发送纯文本,用JSON传递结构化数据(比如
JSON.stringify({type: "dashboard_update", data: {temp:25}})),方便解析和扩展 - 前端重连机制:监听连接断开事件,实现自动重连逻辑,避免网络波动导致服务中断
- 错误捕获与日志:前后端都要捕获WebSocket的错误事件,记录日志并给用户友好提示
- 身份验证:敏感场景下,在WebSocket握手阶段通过Cookie、查询参数传递身份令牌,验证客户端权限
- 高并发优化:如果是大规模实时场景,结合Redis Pub/Sub做分布式广播,避免单进程连接池成为性能瓶颈
内容的提问来源于stack exchange,提问作者Arnold Coto
相关产品推荐
相关产品推荐

