先记住这个答案
AI 聊天主要是一问一答:用户发送完整问题后,服务端分片推送文本。SSE 恰好匹配这条单向数据流,且有 HTTP 层面的事件解析、断线重连和 Last-Event-ID 支持,实现成本低、兼容性好。WebSocket 是双向全双工,适合客户端频繁发送控制信号或需要双工低延迟的交互,但协议复杂且易被中间代理中断。选型先看通信模式:若以服务端推送为主且消息方向明确,用 SSE;若客户端要随时插入指令、改参数或并行语音流,才用 WebSocket。
- 优先SSE,匹配AI单向分片推送
- WebSocket只在双向实时控制才用
- SSE自动重连降低断线恢复成本
SSE 与 WebSocket 交互模型差异
SSE 是服务端向客户端单向推送的标准化协议,基于普通 HTTP 响应,通过 Content-Type: text/event-stream 保持连接。浏览器端 EventSource 自动处理断线重连、事件解析、从 Last-Event-ID 恢复。实现一个 AI 聊天只需要客户端发一次完整 prompt,后续服务端持续推送 delta 文本即可,天然匹配这种请求-响应式流式输出。
WebSocket 在一条 TCP 连接上提供双向消息通道,需要先完成 HTTP 升级握手,客户端可以随时发送任意数据帧。但消息边界、碎片重组、心跳和关闭帧都由应用层管理,中间代理如 Nginx 需特别配置。若没有高频上行消息,比如控制生成、暂停、修改参数,WebSocket 反而增加复杂度和出故障面,而且没有内建重连机制,需要自己实现。
具体场景:一个只发送一次请求的聊天增强
假设构建一个生成法律文件的 web 工具:用户点击按钮后,服务端调用 LLM 并分片返回文本,期间用户不会发任何其他指令。输入是一个文档模板,约束是不希望请求卡在 HTTP 超时之外,且需要让用户看到逐字输出。服务端用 SSE 向同一 HTTP 响应写入 data delta,前端使用 fetch 配合 ReadableStream 逐块解析。缺点是无自动重连但可控性强,因此前端在断线时显示按钮即可,不需要双向通道。
选择这个方案后,可以预期代理或负载均衡可能对 SSE 产生缓冲问题,但通常不会像 WebSocket 那样因企业代理限制而完全断开;后端设置 Cache-Control: no-cache 和 X-Accel-Buffering: no 可缓解。此优化下,路由、鉴权、CORS 仍沿用 HTTP 语义,故障排查只需看响应流和状态码,首 token 延迟则主要取决于模型推理时间。
必须上 WebSocket 的边界与代价
如果产品需求变成:用户在生成过程中可以点“停止”,该命令需要立即发给服务端,SSE 无法承载上行控制指令——只能另发一个 POST /cancel,但可能被代理阻塞或竞争累计。而 WebSocket 的双向通道可复用同一连接收发 cancel 帧,延迟低且可靠。同时若要做实时多模态输入如语音频谱,SSE 的单向上行限制尤为致命,WebSocket 几乎成为唯一选择。
换用 WebSocket 后,必须自己实现心跳、重连和会话一致性。一个常见的破坏条件是服务端在前一轮生成结束后主动关闭连接,但客户端没有及时检测,导致下一次点击时连接已死而静默失败。需要加入 ping/pong 超时判定,并在每次发送前检查 readyState。即便如此,Nginx 默认空闲超时 60s 就会断开,须配置较长 proxy_read_timeout 和 WebSocket 升级。这些额外机制正是 SSE 内建特性的代价。
容易答错的地方
- 认为 WebSocket 一定比 SSE 延迟低
- SSE 使用基于 HTTP 的长连接,与 WebSocket 在 TCP 层延迟相当。真正延迟差异来自握手和头部开销,但 AI 聊天首 token 延迟主要受模型计算影响,协议影响可忽略。选择应基于功能而不仅是延迟。
- 忽略 SSE 也是长连接会占用连接池
- 在 HTTP/1.1 下浏览器对同域最多 6 个连接,SSE 长连接占其一。若同时开多个会话会阻塞其他请求,但 AI 聊天通常每人一个页面,且利用 HTTP/2 多路复用可缓解。这个代价需要与 WebSocket 单独连接的存在性对比,并不构成一定选 WebSocket 的理由。
面试官还会怎么问?
SSE 断线后自动重连如何恢复到未完成的回答位置?
SSE 规范用 Last-Event-ID 让客户端在重连请求头带上已接收的事件 ID,服务端据此跳过已发数据。但生成型 AI 流通常携带业务上下文,需自主实现状态快照。简单方案是每次重连时重新发起整个生成请求,并保证幂等,或用独立的 resume 端点保存生成状态。
WebSocket 连接被中间代理掐断,前端如何检测并可能恢复?
代理断开通常不会主动通知,前端只能通过应用层心跳。设一个定时器每 10s 发 ping,若数秒内无 pong 或 onclose 触发,就标记连接断开。恢复策略:引入连接序号,重连后服务端根据客户端最后收到的消息序号续传,否则重新开始生成。
如果需求是用户可边输入边让 AI 预生成,应该选谁?
边说边生成需要持续上行语音数据,同时下行文本结果,形成双向并发流,必须选 WebSocket。但若上行只是用户敲字,仍属于低频离散消息,用 HTTP POST 结合 SSE 响应即可,网络层更简单。关键在于上行频率和是否要求分片实时。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。