Loading...

【面试真题拆解】为什么用SSE做流式输出?和WebSocket有啥区别?

面试官问:

“你项目里用了SSE做流式输出,为什么选SSE?它的原理你知道吗?为什么不用WebSocket?”

为什么用SSE做流式输出?

一句话:

SSE 是为服务器单向给客户端推数据的场景量身定做的,完美匹配 AIGC 流式打字机的需求,开发简单、好用、运维成本低。

类比:

  • SSE 就像广播电台:电台单向给你播新闻、播音乐,你只能听,不能对着电台说话;
  • WebSocket 就像打电话:你和对方可以双向说话,你一句我一句,实时互动。

SSE流式输出的原理

SSE是Server-Sent Events(服务器发送事件),本质上是一条由服务器控制生命周期的持久化 HTTP 长连接,在数据推送周期内保持打开,不会像普通 HTTP 请求一样响应完成就立刻关闭。

完整的流程就是:

  1. 客户端发起请求

浏览器向服务器发起一个普通的HTTP GET请求,但请求头里要加 Accept: text/event-stream,告诉服务器:“我要接收流式数据,别给我返回普通网页”;

  1. 服务器建立长连接

服务器收到请求后,不立刻返回完整响应,而是保持这条HTTP连接一直打开,不关闭;

  1. 服务器持续推数据

服务器有新数据了(比如AI生成了一个字),就通过这条打开的连接,把数据推给客户端;

SSE 有固定的标准文本格式,每段数据以data:开头、\n\n结尾,刚好适配大模型逐 Token 生成的流式输出,后端生成一个 Token 就推一次,前端无需额外做格式解析,直接渲染成打字机效果;

  1. 客户端解析数据

浏览器收到数据后,自动解析,触发 onmessage 事件,前端把数据展示出来;

  1. 连接结束或自动重连

如果数据推完了,服务器就会主动关闭连接;

如果连接意外断开(非手动关闭、非服务器返回 204 状态码),SSE 自带自动重连机制,浏览器会自动重新发起请求,还会通过请求头Last-Event-ID带上最后接收的消息 ID,后端可据此补发丢失的内容,避免 AI 回答断句缺失,建立新连接后继续接收数据。

为什么不用WebSocket?

WebSocket 是为双向实时交互场景设计的,对于 AI 流式输出这个纯服务器单向推数据的场景,有点那什么杀鸡用牛刀了,并且额外增加了开发、运维成本,完全没有必要。

对比项 SSE(Server-Sent Events) WebSocket
通信模式 单工,纯单向通信:仅支持服务器向客户端主动推送数据,客户端只能被动接收 全双工,双向通信:客户端和服务器可以同时、双向主动发送数据,无请求 - 响应的限制
协议本质 标准 HTTP 应用层协议,完全兼容所有 HTTP 基础设施(Nginx、CDN、网关、防火墙),无需额外配置 独立的应用层协议,底层基于 TCP,仅握手阶段复用 HTTP,握手完成后需协议升级,部分内网网关、WAF 会拦截升级请求
开发复杂度 极低:浏览器原生提供EventSource API,前端几行代码即可实现;后端仅需开发普通 HTTP 接口保持连接推送数据,无需额外处理协议逻辑 较高:需要自行处理连接握手、心跳保活、断线重连、TCP 粘包拆包、帧解析等逻辑,前后端都需要额外的开发工作量
自动重连 原生支持:浏览器内置自动断线重连机制,无需额外开发 无原生支持:需要自行实现心跳检测和断线重连逻辑
适用场景 服务器单向推送场景:AIGC 流式打字机效果、股票行情推送、直播弹幕、新闻实时更新 双向实时交互场景:即时通讯、实时多人游戏、视频会议、物联网设备双向控制
Code Road Record