You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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处理最佳方案
  1. 连接生命周期管理:必须维护连接池,处理连接的添加、移除,同时通过try/finally保证异常断开时连接能被正确清理
  2. 结构化消息:不要直接发送纯文本,用JSON传递结构化数据(比如JSON.stringify({type: "dashboard_update", data: {temp:25}})),方便解析和扩展
  3. 前端重连机制:监听连接断开事件,实现自动重连逻辑,避免网络波动导致服务中断
  4. 错误捕获与日志:前后端都要捕获WebSocket的错误事件,记录日志并给用户友好提示
  5. 身份验证:敏感场景下,在WebSocket握手阶段通过Cookie、查询参数传递身份令牌,验证客户端权限
  6. 高并发优化:如果是大规模实时场景,结合Redis Pub/Sub做分布式广播,避免单进程连接池成为性能瓶颈

内容的提问来源于stack exchange,提问作者Arnold Coto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 09:45:28