SSE 和 WebSocket 到底怎么选?

栏:AI 全栈开发|14

|-----------------------------------------------------------------------------------------------------------------------------|
| 前两篇已经分别把 SSE 和 WebSocket 学清楚。现在不再重复协议定义,而是回答真正会遇到的工程问题:一个 AI 产品到底应该在哪条链路用 SSE,在哪条链路用 WebSocket?判断依据不是"哪个更先进",而是你的通信形状和产品约束。 |

一、先看两个"都能做,但复杂度不同"的例子

场景 1:AI Chat

用户点一次发送,服务器开始持续返回模型输出。

|----------------------------------------------------------------------|
| Browser ── POST /chat ──▶ Server Browser ◀── Streaming/SSE ── Server |

客户端确实也有上行数据,但它不是"持续高频上行",而是一次明确的请求。

这种场景完全没必要因为"客户端也会发消息"就立刻上 WebSocket。

场景 2:在线协作编辑

|-------------------------------------------------------------------------|
| Browser A ◀════▶ Server Browser B ◀════▶ Server Browser C ◀════▶ Server |

光标、选区、编辑操作、在线状态都可能由双方随时发送。这里用一条长期双向通道会自然很多。

图 1 第一问是通信形状:一次请求 + 持续返回、单向持续推送,还是双方长期高频互发

二、第一条判断:客户端到底是不是"长期主动发送"

很多选型文章只说"单向选 SSE,双向选 WebSocket",这还不够精确。

因为 AI Chat 明明也存在双向通信:用户要把 prompt 发给服务器,用户还要点 Stop。

真正值得问的是:

客户端是否需要在同一条长期连接里,持续、低延迟、主动发送大量事件?

如果上行只是:

• 发一次 prompt。

• 偶尔取消任务。

• 修改一次配置。

普通 HTTP POST 已经很好。下行再用 SSE / Streaming 即可。

如果上行是:

• 持续输入位置。

• 实时控制指令。

• 多人协作操作。

• 游戏状态。

WebSocket 会更自然。

三、不要只看方向,还要看这 6 个维度

图 2 方向性只是第一维;请求方式、浏览器 API、重连、状态恢复和基础设施都会影响最终选型

|---------|---------------------------|------------------------------|
| 维度 | SSE / Streaming | WebSocket |
| 通信形状 | 服务器持续推送为主 | 双方长期主动收发 |
| 客户端上行 | 通常搭配普通 HTTP 请求 | 直接在同一连接发消息 |
| 浏览器 API | EventSource 或 fetch | WebSocket |
| 重连 | EventSource 可自动尝试重连 | 浏览器端需要自己实现 |
| 断点恢复 | 可利用 id / Last-Event-ID 设计 | 自己设计 seq / replay / snapshot |
| 消息类型 | SSE 是 UTF-8 文本事件 | Text / Binary Message |
| 生命周期 | HTTP 流连接 | 独立长期连接状态 |

四、EventSource 不是 SSE 的全部,SSE 也不只适合 GET

如果 AI Chat 需要:

|---------------------------------------------|
| POST /chat { "message": "解释一下 Agent Loop" } |

然后同一个 HTTP 响应持续返回 SSE 事件,可以直接用 fetch() 读取 text/event-stream。

所以:

• SSE 是事件格式。

• EventSource 是消费 SSE 的一种浏览器 API。

• POST + fetch SSE 同样是常见 AI Chat 方案。

这点会直接影响选型:不要因为 EventSource 只能 GET,就误判"聊天必须 WebSocket"。

五、WebSocket 也不是因为"全双工"就一定更快

建立 WebSocket 以后,后续消息确实不需要为每条业务消息重新建立 HTTP 请求语义。

但用户真正感知的延迟还取决于:

• 网络 RTT。

• 后端排队和处理时间。

• 模型推理耗时。

• 代理和服务端实现。

对于 LLM 生成这种动辄几百毫秒甚至数秒的任务,HTTP / SSE 的额外开销往往不是主要瓶颈。

所以不能简单写成"低延迟就一定 WebSocket"。

六、重连:SSE 确实省事,但不是"可靠消息自动完成"

EventSource 的自动重连很方便;WebSocket 浏览器端需要自己写重连。

但二者断线以后都要问:

断线期间发生的数据怎么办?

SSE 可以配合:

|--------------------------------------------|
| id: 120 data: ... # 重连时浏览器提供 Last-Event-ID |

但前提是服务端保存了事件历史,并且知道怎样从 121 开始重放。

WebSocket 则通常自己定义:

|--------------------------------------------|
| last_seq = 120 reconnect() sync(after=120) |

所以"自动重连"和"状态恢复"是两件不同的事。

七、认证:两边都能做,但方式不同

SSE / EventSource

EventSource 不能像 fetch 一样任意加 Authorization Header。常见方案包括同源 Cookie、withCredentials,或者先 POST 创建任务后拿一个不可预测的短期订阅 ID。

fetch SSE

如果用 fetch 消费 SSE,就可以正常使用 POST、Authorization Header 等 fetch 能力。

WebSocket

浏览器 new WebSocket() 同样不能随意设置自定义 Authorization Header。常见做法包括 Cookie、短期 ticket、Subprotocol 等设计。

|-------------------------------------------------------------------------|
| 因此不要写成"WebSocket 鉴权更灵活,因为握手可以随便带 Header"。在浏览器 API 下,两者都有约束,应该从实际认证架构设计。 |

八、代理与基础设施:SSE 不等于"完全白嫖 HTTP 基建"

SSE 建立在 HTTP 上,通常更容易接入现有 Web 基础设施,这是优势。

但仍然可能遇到:

• 代理缓冲导致不流式。

• CDN / LB idle timeout。

• 长响应超时配置。

• 压缩或中间件缓冲。

WebSocket 则需要中间层支持连接升级或对应的现代 WebSocket 建连方式,并管理长期连接。

但现代 Nginx、云负载均衡和网关对 WebSocket 支持已经很成熟,不能简单写成"WebSocket 很难穿代理"。

九、连接数和资源:不要简单说"WebSocket 比 SSE 贵很多"

两者都是长时间保持连接。

每个在线客户端都可能占用:

• 连接状态。

• 文件描述符 / socket 资源。

• 服务端内存和缓冲区。

• 心跳或超时管理。

具体哪个更贵,取决于实现、HTTP 版本、网关、消息频率和业务状态,不能仅凭协议名字下结论。

真正的容量规划要压测。

十、多实例部署真的必须 Sticky Session 吗

WebSocket 一条已经建立的连接当然会落在某个具体实例上。

但这不等于"整个 WebSocket 系统必须 sticky session"。

如果用户重连后落到另一个实例,只要:

• 认证状态可共享。

• 房间 / 订阅状态可以恢复。

• 跨实例消息通过 Redis、Kafka、NATS 等机制分发。

完全可以正常工作。

Sticky Session 是一种部署策略,不是 WebSocket 协议要求。

SSE 同样可能需要共享事件源,否则重连到另一个实例也无法续传。

十一、一个 AI 产品里,三种通道完全可以同时存在

图 3 按业务链路选协议:普通 REST、Streaming/SSE、WebSocket 可以在同一个产品里并存

例如一个完整 AI 工作台:

|-----------|------------------------|
| 业务链路 | 推荐方式 |
| 发送 Prompt | POST /chat |
| 模型增量输出 | fetch Streaming / SSE |
| 停止生成 | POST /runs/{id}/cancel |
| 后台任务进度 | SSE |
| 多人协作编辑 | WebSocket |
| 普通 CRUD | REST API |

这个设计反而比"全站统一 WebSocket"或者"所有实时都 SSE"更容易理解和维护。

十二、快速选型:按问题问,而不是按协议背

|-------------------|-----------------|-----------------------------|
| 先问什么 | 如果答案是...... | 更值得先考虑 |
| 服务器推为主吗? | 是 | SSE / Streaming |
| 客户端需要长期高频主动发吗? | 是 | WebSocket |
| 只有一次 POST + 长输出吗? | 是 | fetch Streaming / SSE |
| 需要浏览器自动重连吗? | 很重要 | EventSource SSE 有优势 |
| 需要二进制双向消息吗? | 是 | WebSocket |
| 断线必须无缝恢复吗? | 是 | 两者都要额外设计事件历史 / seq / replay |

十三、几个最容易背错的结论

• 误区 1:单向一定 SSE、双向一定 WebSocket。偶尔上行 POST + 持续下行仍然很适合 SSE。

• 误区 2:AI Chat 教科书级必须 SSE。fetch Streaming 也很常见;具体选事件协议还是裸流取决于前端事件需求。

• 误区 3:WebSocket 天生比 SSE 更低延迟。真实延迟由整条链路决定。

• 误区 4:SSE 自动重连就自动断点续传。服务端仍要保存和重放事件。

• 误区 5:WebSocket 一定需要 Sticky Session。Sticky 只是多实例架构中的一个可选策略。

• 误区 6:股票行情 / 在线游戏都只能 WebSocket。行情如果只是单向推送也可能使用 SSE;游戏、音视频还可能需要更专门的实时协议。

十四、下一篇

下一篇 15《同步、异步、并发到底有什么区别?》会离开具体传输协议,开始看 FastAPI 后端真正的运行模型:为什么等待模型 API 时 async 很有价值,为什么 CPU 密集任务不能因为加了 async def 就自动变快。

相关推荐
Rocky Ding*1 小时前
一文读懂Hallo数字人核心基础知识
论文阅读·人工智能·深度学习·机器学习·aigc·数字人·ai-native
byte轻骑兵1 小时前
【BlueZ】 log 模块:日志系统的实现与自定义日志输出配置
linux·人工智能·bluez·电脑蓝牙·嵌入式蓝牙
AI码农小姐姐1 小时前
AI漫剧推文短视频动态镜头实现:FFmpeg zoompan 与 Ken Burns 效果实践
人工智能·音视频·ai工具·ai漫剧
技灵AI1 小时前
ChatGPT Images 2.5 深度解读:延迟减半、Sketch 草图与 Flare/Sunburst 双模型 API
人工智能·gpt·aigc·音视频·images2.5
Geek-Chow1 小时前
12. 完整重演:一句话请求的完整旅程 + 动手练习
人工智能
m0_734571761 小时前
深入理解人工智能chatGPT 外部工具与知识增强层 (Tools & RAG Layer)
人工智能·chatgpt
智能运维指南1 小时前
2026年企业自动化运维平台选型:四类架构的差异与决策逻辑
运维·人工智能·嘉为蓝鲸
user_admin_god1 小时前
第 01 篇:OpenAI 兼容 API 初探 —— 用 curl 跑通第一次对话
java·人工智能·spring boot·语言模型·devops
梦帮科技1 小时前
RNS 代币架构:ERC20 五件套扩展与六钱包分配
人工智能·sql·区块链·database·合成复用原则·加密货币