AI 流式输出都用 SSE,什么时候必须换 WebSocket?
上个月,我们的 AI 客服助手全量上线,第三天运维就找上门:问答接口的 QPS 莫名翻了一倍,客服还收到一堆投诉,说回答半天不吐字,用户以为卡死,点一次发一次,重试越点越多。
查了一圈,根因不在大模型,而在传输层。Nginx 默认把流式响应缓冲起来攒一波再吐,首字硬生生拖到 8 秒;前端用的还是最省事的裸 EventSource,断了不报错、慢了不提示,用户只能靠狂点续命。重试流量反过来又压垮网关,恶性循环。
这就是流式场景最真实的场景:模型没问题,管子先爆了。今天就把这根管子讲透,什么时候 SSE 够用,什么时候必须换 WebSocket,以及各自的坑怎么填。
出问题后,组里出现两种声音。一种说 EventSource 一行代码就能跑,别折腾;另一种说干脆全量切 WebSocket,一劳永逸。这两条路我都踩过,都有坑,只是结果不同。
EventSource 的 API 是只读的:只支持 GET,不支持自定义请求头。token 只能拼在 URL 上,网关日志、CDN 日志、浏览器历史全是明文,安全评审直接打回。断线重连看似自动,实则裸奔:没有服务端配合回放 Last-Event-ID,重连后要么丢消息,要么从头发完整流,用户会看到回答闪一下重打一遍。更隐蔽的是超时,Nginx 默认 proxy_buffering on,流式响应会被攒批,首字时间完全不可控。
WebSocket 是长连接,网关要为每个连接维持状态,连接数直接变成成本。我们的客服页是低频使用的页面,用户问完就关,为这种低频、单向、下行主导的流量维持全双工连接,实例数要翻几倍。移动端更惨,切后台、锁屏、进电梯,连接一断就得整套重连、重鉴权、重订阅,心跳和退避策略全要自己写。
结论很清晰了👉:下行主导、低频、低延迟要求不极致,用 SSE;双向实时、高频上行、需要服务端主动推且客户端也要频繁说话,才上 WebSocket。比如多轮问答、摘要生成是 SSE 的主场;协作编辑、语音对讲、实时游戏状态同步,才是 WebSocket 的主场。
先看大多数人写的版本,十五分钟能跑,三个月后必返工:
生产级版本必须同时解决四件事:POST + token 请求头鉴权、可取消、断线按 Last-Event-ID 续接、退避重试。直接上代码:
用法上配合 AbortController 做取消,组件卸载或用户点停止时直接 abort,不再有幽灵请求:
客户端写结实了,线上照样可能翻车。下面 👇 四个全是生产里真金白银换来的,每个都给兜底。
Nginx 默认 proxy_buffering on,会把上游的流攒成块再吐,流式直接退化成轮询。兜底要在 location 里显式关掉,并让上游声明不缓冲:
服务端再补一个响应头 X-Accel-Buffering: no,双保险。验收标准只有一个:首字时间进监控,超过 3 秒直接告警,别等用户投诉🤷♂️。
HTTP/1.1 下浏览器对同一域名只有 6 个并发连接,SSE 一旦连上就长期占一个。用户开三个问答标签页,再加载页面资源就开始排队,页面转圈的锅最后全算在前端头上。兜底策略:全局限制同页 SSE 并发数为 1,后开的流先 abort 前一个;切 HTTP/2 则多路复用天然缓解,但网关的 stream 并发上限同样要核对,别从浏览器瓶颈换成网关瓶颈👋。
网络抖动是常态,重连后服务端从 Last-Event-ID 重放,客户端如果直接追加,用户会看到半截回答突然重来一遍。正确做法是按 ID 去重 + 按位点替换:维护已收 ID 集合,重放的消息只用于补位不重复渲染;服务端必须保证 ID 单调递增,这是前后端要对齐的契约,不是前端单方面能解决的🫡。
多数网关默认 60 秒无数据就掐连接,大模型思考超过 60 秒不吐字,连接就被静默掐掉。兜底是服务端每 15 秒发一条注释心跳(:\n\n),既保活又不污染业务流;客户端加一层兜底计时器,30 秒无任何字节就主动重连。同时统计要洗干净:重连次数、首字时间、完整率单独上报,别把重连算进接口成功率里,否则监控一片祥和,线上全是断流。
最后给一张决策表,贴在组里能少吵很多架。出现下面任意一条,SSE 不要硬撑,直接上 WebSocket!
WebSocket 也不是换过去就完事,心跳、重连退避、token 过期重鉴权,一行都不能少:
注意 token 过期时不要无脑重连,先刷新 token 再建连,否则重连风暴里全是 401,网关日志会被打爆。
流式传输的技术选型,从来都是成本多少的问题。SSE 便宜、简单、和 HTTP 基础设施处得来,配上可取消、可续接的客户端,能覆盖九成 AI 问答场景;WebSocket 留给真正双向的场景。但是别让低频页面替长连接买单!
喜欢我的文章,也欢迎关注我的微信公众号:【前端技术官】。
主要分享:前端架构 · AI 编程 · 职场认知 · 开发者成长
来源:稀土掘金 原文