文章

SSE 还是 WebSocket?大模型流式接口的前端选型

对接过两种方案之后,聊聊大模型对话场景下 SSE 与 WebSocket 各自的脾气。

SSE 还是 WebSocket?大模型流式接口的前端选型

做 AI 安全平台时对接过 SSE 的推理接口,做地震应急系统时维护过 WebSocket 的实时预警通道。两种”流”都伺候过之后,经常被问:大模型对话到底该用哪个?

先给结论:对话类场景默认 SSE,需要双向控制或多会话并发时才考虑 WebSocket。下面说为什么。

先看数据流的形状

大模型对话的通信模式是”一问一大串”:客户端发一个短请求,服务端回一条持续几秒到几十秒的 token 流。请求短、响应长、方向单一——这个形状天然就是 SSE 的形状。

SSE(Server-Sent Events)本质是一个不关闭的 HTTP 响应,text/event-stream 一行一个事件。它的好处全部来自”它就是 HTTP”:

  • 不用自己养连接。每次对话开一个请求,流完即走,没有心跳、没有连接池
  • 断线重连是浏览器原生的EventSource 自带 retry 和 Last-Event-ID
  • 基础设施友好。网关、代理、鉴权中间件把它当普通 HTTP 请求,不需要为 Upgrade 开洞

实践里有一个绕不开的细节:原生 EventSource 只支持 GET、不能带自定义头。大模型请求几乎都是带 body 的 POST,所以实际用的是 fetch + ReadableStream 手动解析 event-stream 格式——多写几十行解析代码,换来完整的请求控制权,值得。

WebSocket 的账要算两本

WebSocket 给你真正的双向通道,但账要算两本。

能力账:对话场景里,客户端在响应期间要对服务端说的话其实只有一句——”停止生成”。而这句用 SSE 也能做:AbortController.abort() 掐断请求,服务端感知连接断开即停止推理。为一句话上双向通道,能力是闲置的。

运维账:这本才是大头。我在地震预警通道上维护过完整的一套:心跳保活(不发心跳,中间设备静默断你没商量)、指数退避重连、重连后的状态同步、token 过期后的连接内鉴权续期。WebSocket 不是接上就完了,它是一条要每天喂的狗。

那什么时候 WebSocket 是对的?我的判断标准:

  • 服务端要主动推送与请求无关的消息(如多人协作、系统广播)
  • 一条连接上要并发多路会话,靠消息里的会话 ID 分发
  • 交互频繁到 HTTP 每次握手的开销真的可观

地震预警就是典型:服务端随时可能广播,客户端常驻监听——那是 WebSocket 的主场。

无论选哪个,前端都要做的事

选型只是开始,这几件事两种方案都逃不掉:

  • 消息完整性:SSE 事件可能在任意字节处被截断,chunk 拼接要按分隔符切,不能假设一次 read() 是一条完整消息
  • 背压:渲染速度跟不上 token 速度时要攒批(见我另一篇《大模型流式渲染踩坑记》)
  • 异常兜底:流中断要能区分”正常结束”、”用户停止”、”网络断开”,三种状态给用户的界面反馈完全不同

结语

技术选型最怕”哪个新用哪个”。SSE 老、朴素、单向,但大模型对话的数据流形状恰好就是它的形状。别为用不上的能力去养一条连接——这是两个项目换来的一句话。

本文由作者按照 CC BY 4.0 进行授权