← 返回题目列表

FastAPI 如何支持 WebSocket?WebSocket 和普通 HTTP 接口有什么区别?

高频 中等 第 9 / 27 题 更新于 2026/07/31
FastAPIWebSocketASGI长连接

简化版

FastAPI 基于 ASGI,原生支持 WebSocket。普通 HTTP 是一次请求一次响应,WebSocket 是建立长连接后双向通信,适合实时聊天、通知、仪表盘推送等场景。WebSocket 要处理连接管理、认证、心跳、断开、广播和背压。

详细版

@app.websocket("/ws")
async def websocket_endpoint(ws: WebSocket):
    await ws.accept()
    try:
        while True:
            text = await ws.receive_text()
            await ws.send_text(f"echo: {text}")
    except WebSocketDisconnect:
        ...

WebSocket 不是简单的长轮询替代品。它会长期占用连接和服务端资源,生产中要考虑最大连接数、消息大小、鉴权、断线重连和多实例广播。

完整版教学

一、为什么 WebSocket 需要 ASGI

WSGI 是同步请求响应模型,不适合双向长连接。ASGI 支持事件消息模型,可以表达连接建立、接收消息、发送消息和断开。

HTTP: request -> response -> end
WebSocket: connect -> message* -> disconnect

FastAPI 依赖 Starlette 和 ASGI,因此可以原生处理 WebSocket。

二、基本连接流程

WebSocket 处理函数接收 WebSocket 对象。先 accept(),再循环接收和发送消息。客户端断开时会抛 WebSocketDisconnect

accept
  |
receive_text
  |
send_text
  |
disconnect

如果没有 accept,连接不会正式建立。

三、认证怎么做

WebSocket 不能像普通请求那样每次带完整 HTTP 交互。常见方式是在握手时带 Cookie、Query token 或 Header,然后服务端校验。

token = ws.query_params.get("token")

认证失败可以关闭连接。生产中 token 不要随便放 URL,避免被日志记录;能用 Cookie 或短期 token 更好。

四、连接管理和广播

聊天室或通知系统需要保存活跃连接。单进程里可以用列表或集合管理;多进程多实例时,内存连接表只在本进程有效,跨实例广播要用 Redis pub/sub、消息队列等。

worker A connections: 100
worker B connections: 120
广播 -> 需要跨 worker 通知

这和 Flask 全局变量问题类似,内存状态不是全局事实来源。

WebSocket 的难点不是 echo demo,而是连接生命周期和多实例协作。

五、心跳和断线处理

长连接可能因为网络、代理、客户端崩溃而半断开。服务端需要心跳、超时和异常处理,及时清理连接表。

ping/pong
超时 -> close -> remove connection

如果不清理,连接管理器里会残留无效连接,广播时不断失败。

六、背压和消息大小

客户端慢或网络慢时,服务端发送过快会堆积。要限制消息大小、发送频率、队列长度,必要时断开慢消费者。

生产 1000 msg/s
客户端消费 100 msg/s
积压 900 msg/s

实时系统不能只追求推送快,还要有降级和丢弃策略。

七、常见误区与追问

  • 误区:WebSocket 比 HTTP 一定更好。 它适合实时双向通信,不适合所有接口。
  • 误区:连接表放全局 list 就能多实例广播。 只在当前进程有效,多实例要外部消息系统。
  • 误区:WebSocket 不需要认证。 握手阶段也必须认证授权。
  • 追问:断开如何处理? 捕获 WebSocketDisconnect,清理连接。
  • 追问:如何广播? 单进程内遍历连接,多实例用 Redis pub/sub 等。
  • 追问:心跳有什么用? 发现半开连接,释放资源。
  • 追问:WebSocket 和 SSE 怎么选? 双向用 WebSocket,单向服务端推送可考虑 SSE。

八、加强记忆

FastAPI WebSocket 记成“ASGI 长连接双向消息”。代码 demo 很短,生产重点是认证、连接管理、心跳、断线、多实例广播和背压。能讲这些,才算真正理解 WebSocket 工程化。