1. 核心回答
AI 对话通常是客户端发一次请求,服务端持续把模型生成的结果流回来,所以 SSE 更贴合这个通信模型,而且基于 HTTP,接入和维护成本也比较低。
这句话先说到这里。不要一上来就讲:
SSE 单向、WebSocket 双向、SSE 自动重连……
这些属于面试官继续追问后的展开。
2. AI 对话到底是什么通信模型?
先看最典型的文本对话:
用户输入问题 │ ▼ 客户端 ─────── 请求 ───────► AI 服务 │ ▼ 调用模型 │ 持续生成 Token │ ┌────────────────┼──────────────┐ ▼ ▼ ▼ Token Token Token │ │ │ └────────────────┼──────────────┘ ▼ 客户端 ◄──────── 持续返回生成结果 ────────核心就是:
客户端主要负责发起请求,服务端负责持续把生成结果推回来。
例如:
客户端:帮我解释一下 React Fiber ↓ 服务端:React ↓ 服务端:React Fiber ↓ 服务端:React Fiber 本质上…… ↓ 服务端:……客户端并不需要在生成过程中不断向服务端发送消息。所以它非常接近:
一次请求 ↓ 持续响应这就是 SSE 非常适合的通信模型。
3. 为什么 AI 对话特别适合 SSE?
这里可以明确记住三个原因。
第一:通信模型匹配
SSE 的核心就是:
客户端 ───── HTTP 请求 ─────► 服务端 客户端 ◄════ 持续事件流 ════ 服务端也就是:
客户端发起请求,服务端持续向客户端推送数据。
而 AI 文本对话恰好就是这个模型。
第二:SSE 基于 HTTP,接入成本低
SSE 本身就是 HTTP 响应流。典型请求:
GET /api/chat/stream Accept: text/event-stream服务端保持响应连接,然后不断返回:
data: {"content":"你"} data: {"content":"好"} data: {"content":","} data: {"content":"世界"}所以现有 HTTP 基础设施基本都可以继续使用:
浏览器 ↓ CDN / 反向代理 ↓ 负载均衡 ↓ Nginx ↓ 应用服务器WebSocket 则需要通过 HTTP Upgrade 完成握手,之后切换成 WebSocket 协议进行双向通信。所以不是:
WebSocket 不能走 HTTP。
而是:
WebSocket 借助 HTTP Upgrade 建立连接,握手完成后就进入 WebSocket 的双向通信阶段。
第三:AI 本身就是流式文本输出
这是 AI 场景非常重要的一点。模型不是一定要等整个答案生成完才返回。可以:
生成一个 Token ↓ 马上发送 ↓ 前端马上渲染 再生成一个 Token ↓ 马上发送 ↓ 前端继续渲染所以用户看到的是:
React Fiber 本质上是... ↓ React Fiber 本质上是一种... ↓ React Fiber 本质上是一种可中断...而 SSE 天然就是:
服务端持续发送文本事件。
所以和 AI 的流式输出非常契合。
4. SSE 和 WebSocket 到底有什么区别?
最核心就看通信模型:
SSE: Client ───────────────► Server HTTP Request Client ◄═══════════════ Server Event Stream而 WebSocket:
Client ◄═══════════════► Server 双向通信所以:
| SSE | WebSocket | |
|---|---|---|
| 核心方向 | 服务端 → 客户端 | 双向 |
| 建立连接 | HTTP | HTTP Upgrade |
| 后续通信 | HTTP 响应流 | WebSocket 帧 |
| 文本流 | 很适合 | 适合 |
| 二进制 | 不适合 | 很适合 |
| 客户端持续发送 | 不适合 | 适合 |
| 浏览器原生自动重连 | EventSource支持 | 需要自行实现 |
| 双向高频通信 | 不适合 | 适合 |
但要注意:
SSE 不是“客户端不能发请求”。
客户端当然可以:
POST /api/chat向服务端发送消息。只是:
SSE 本身只定义服务端到客户端的事件流,不提供一个同时存在的客户端到服务端消息通道。
因此实际 AI 应用完全可以:
POST /api/chat ↓ 提交用户问题 GET /api/chat/stream ↓ SSE 接收模型输出或者根据具体设计把请求和流式响应组合成一次 HTTP 交互。
5. WebSocket 能不能做 AI 对话?
当然可以。
Client ◄════════ WebSocket ════════► AI Server然后:
Client → 用户问题 Server → Token 1 Server → Token 2 Server → Token 3 Server → Token 4技术上没有问题。所以真正正确的说法不是:
AI 对话不能用 WebSocket。
而是:
对于以服务端流式输出为主的 AI 文本对话,WebSocket 提供的双向能力很多时候用不上,因此 SSE 往往更简单。
这才是技术选型。
6. SSE 的自动重连到底怎么回事?
浏览器原生:
constsource=newEventSource('/api/chat/stream');source.onmessage=(event)=>{console.log(event.data);};连接断开之后,EventSource会按照 SSE 的规则尝试重新连接。
服务端还可以返回:
retry: 3000告诉客户端重连等待时间。SSE 还有一个很重要的东西:
id: 101 data: hello如果连接断开,浏览器重新连接时可以带上:
Last-Event-ID: 101服务端就可以根据这个 ID 判断:
客户端最后收到的是 101 那么可以从 102 开始继续但是这里一定要说准确:
SSE 提供了自动重连和 Last-Event-ID 这样的能力,但不等于自动保证业务消息不丢。
真正的断线恢复还需要服务端保存事件、判断从哪里恢复以及处理重复消息。
7. WebSocket 为什么通常需要自己做重连?
WebSocket:
constws=newWebSocket(url);ws.onopen=()=>{};ws.onmessage=()=>{};ws.onclose=()=>{};ws.onerror=()=>{};连接断了之后:
onclose ↓ 自己决定是否重连 ↓ 等待 ↓ 重新连接 ↓ 重新鉴权 ↓ 恢复订阅 ↓ 处理未确认消息线上一般还会进一步做:
断线检测 ↓ 指数退避 ↓ 最大重试次数 ↓ 重新鉴权 ↓ 恢复订阅 ↓ 消息恢复 / 重放如果业务对可靠性有要求,还可能需要:
messageId ACK sequence 重放 幂等所以区别不是:
WebSocket 没有重连。
而是:
WebSocket 不像 EventSource 那样直接提供浏览器级的自动重连体验,业务需要自己设计连接恢复方案。
8. 那 SSE 一定比 WebSocket 省服务器资源吗?
不能这么说。实际资源消耗取决于:
连接数量 消息频率 消息大小 连接持续时间 服务端实现 代理层 心跳频率 发送缓冲 业务状态例如:
100 万长连接无论 SSE 还是 WebSocket,都不是“没有成本”。都需要面对:
Socket 文件描述符 内核缓冲区 用户态连接对象 网络带宽 TLS 事件循环 连接管理所以更准确的说法是:
SSE 在单向流式场景下协议和业务模型更简单,但不能简单认为 SSE 天然比 WebSocket 省固定比例的 CPU 或内存。
真正需要优化时应该压测。
9. 为什么 WebSocket 在大规模连接下可能更复杂?
WebSocket 是双向长连接,服务端通常需要长期维护连接以及与连接关联的业务状态。
例如:
用户 ↓ WebSocket Connection ↓ 用户 Session ↓ 订阅关系 ↓ 消息状态 ↓ 发送队列当连接数非常大的时候:
10 万 100 万 1000 万连接管理本身就成为架构问题。尤其当业务状态直接绑定到某台机器:
Client ↓ Server A ↓ Connection State这时候扩容成:
Server A Server B Server C就必须考虑:
连接到底在哪台服务器? 业务消息在哪台服务器产生? 怎么找到对应连接? 服务器之间怎么通信?10. SSE 是不是天然无状态?
不是。
这一点一定不要答错。SSE 只是通信方式。你完全可以设计成:
Client ↓ SSE ↓ Server ↓ 连接状态也可以:
Client ↓ SSE ↓ Server ↓ Redis / MQ / DB ↓ 业务状态所以:
SSE 不等于无状态,WebSocket 也不等于一定有状态。
更准确的是:
WebSocket 的持续双向连接更容易产生连接级状态,因此大规模水平扩展时,需要重点处理连接与业务状态的解耦。
11. SSE 怎么做水平扩展?
例如:
Load Balancer / | \ / | \ Server A Server B Server C \ | / \ | / Redis / MQ假设:
用户的 SSE 连接 ↓ Server A但是:
AI 模型生成结果 ↓ Server CServer C 不能直接假设:
用户连接就在我这里。
所以可以:
AI Worker ↓ Redis / MQ ↓ Server A ↓ SSE ↓ Browser这样:
AI 任务处理和 SSE 连接管理就可以解耦。
当然,具体用 Redis Pub/Sub、Stream、Kafka、消息队列还是其他方案,要根据可靠性、吞吐和数据生命周期选择。
12. SSE 能不能上传图片?
SSE 本身不负责文件上传。但是这完全不是问题。
例如:
┌──── HTTP Multipart ────► 文件服务 │ Client ──────┤ │ └──── Chat Request ──────► AI 服务 │ ▼ AI 推理 │ ▼ Client ◄──────────── SSE Stream ─────────────┘也就是:
图片: HTTP 上传 AI 输出: SSE 流式返回所以:
“AI 要上传图片,所以必须用 WebSocket”是错误的。
甚至大文件上传本身通常也更适合 HTTP,因为可以利用:
multipart 分片上传 断点续传 对象存储 CDN 上传进度13. 那什么时候应该用 WebSocket?
这时候看业务。如果是:
用户发一个问题 ↓ AI 持续返回答案优先考虑:
SSE如果变成:
Client ◄════════════► Server双方都需要持续、高频、实时通信:
用户操作 ↓ 服务器 ↓ 其他用户 服务器状态 ↓ 客户端 客户端控制指令 ↓ 服务器就更适合 WebSocket。
典型场景:
实时协作
用户 A ↓ 修改文档 ↓ Server ↓ 用户 B / C / D在线游戏
客户端 → 移动 客户端 → 攻击 客户端 → 技能 服务端 → 状态同步 服务端 → 战斗结果 服务端 → 其他玩家双向实时控制
例如:
Client ⇄ AI Agent客户端持续发送控制指令,同时服务端持续返回状态,这时候 WebSocket 就更自然。
14. AI 语音为什么又不一定适合 SSE?
这是很好的追问。假设是实时语音:
麦克风 ↓ 持续上传音频 ↓ 服务端 ↓ AI ↓ 持续返回音频 ↓ 扬声器实际上是:
Client ◄══════════► Server而且:
客户端持续上传 + 服务端持续返回这是典型的双向实时通信。所以这类场景通常会考虑:
WebSocket或者对实时媒体传输要求更高时考虑:
WebRTC因此千万不要形成:
AI = SSE。
正确的是:
AI 文本对话很适合 SSE,但 AI 不等于 SSE。具体协议还是取决于通信模型。
15. SSE 还有一个非常重要的工程坑:代理缓冲
如果面试官继续往深处问,这个很容易区分是否真正做过 SSE。
SSE 要的是:
服务端生成一点 ↓ 马上发给浏览器但如果中间代理把数据缓存起来:
Server ↓ Proxy ↓ 缓存 10KB ↓ 一次性返回 ↓ Browser那么用户看到的就不是:
一个字一个字出来而是:
等一会儿 ↓ 突然出来一大段所以实际部署 SSE 时,要关注:
代理缓冲 响应压缩 空闲超时 连接超时 HTTP/2 / HTTP/3例如 Nginx 场景通常需要关闭响应缓冲,否则流式效果可能被破坏。这个点比单纯背:
SSE 是单向,WebSocket 是双向
要高级很多。
16. AI 对话到底怎么选?
可以直接记这张图:
AI 通信需求 │ ┌───────────┴───────────┐ │ │ 服务端流式输出 双向实时通信 │ │ ▼ ▼ SSE WebSocket │ │ AI 文本生成 实时协作 流式回答 在线游戏 实时通知 双向控制 日志流 实时交互如果进一步考虑:
双向实时音视频 ↓ WebRTC所以协议选择可以简单理解成:
单向流式输出 → SSE 双向实时消息 → WebSocket 实时音视频媒体 → WebRTC但这只是第一层判断,真正的工程选型还要继续考虑:
可靠性 连接规模 部署环境 代理/CDN 断线恢复 消息顺序 状态管理 扩展方式 开发维护成本17. 这道题真正考什么?
它表面上问:
为什么 AI 对话用 SSE,而不是 WebSocket?
实际上考的是:
你能不能根据业务需求和工程约束做技术选型,而不是只会背 API。
普通回答:
SSE 单向,WebSocket 双向。
只能拿到基础分。更好的回答:
AI 文本对话本身就是客户端发起请求、服务端持续流式输出,所以 SSE 的通信模型更匹配;同时 SSE 基于 HTTP,浏览器有 EventSource 和自动重连能力,接入现有 HTTP 基础设施也比较自然。WebSocket 的优势在于双向实时通信,如果业务需要客户端和服务端持续高频交互,它反而更合适。
这才是完整的第一层。
18. 高频追问链
这道题建议直接按照下面这条链准备:
为什么 AI 用 SSE? ↓ SSE 和 WebSocket 的通信模型区别? ↓ SSE 为什么适合流式输出? ↓ SSE 为什么基于 HTTP? ↓ WebSocket 怎么建立连接? ↓ HTTP Upgrade 做了什么? ↓ SSE 怎么自动重连? ↓ Last-Event-ID 是干什么的? ↓ WebSocket 怎么做重连? ↓ SSE / WebSocket 谁更省资源? ↓ 100 万连接服务器扛不住怎么办? ↓ SSE 怎么水平扩展? ↓ 多服务器之间怎么传 AI 流? ↓ Redis / MQ 在这里干什么? ↓ SSE 能不能上传图片? ↓ AI 实时语音怎么办? ↓ 什么时候应该用 WebSocket? ↓ SSE 部署在 Nginx / CDN 后有什么坑?19. 最终满分答案
如果面试官问:
“为什么 AI 对话普遍用 SSE,而不是 WebSocket?”
你可以直接回答:
AI 对话通常是客户端发一次请求,服务端持续把模型生成结果流回来,所以 SSE 的通信模型更匹配。它又是基于 HTTP 的,浏览器通过 EventSource 就能直接接收事件流,并且具备自动重连能力,所以整体接入和维护成本比较低。
WebSocket 当然也能做 AI 对话,只是它的优势主要是双向实时通信。如果业务需要客户端和服务端持续、高频地互相发送消息,比如实时协作、在线游戏、双向实时控制,那 WebSocket 更合适。
所以我不会简单认为 SSE 比 WebSocket 更好,而是看通信模型:服务端流式输出优先考虑 SSE,双向实时通信考虑 WebSocket;如果是实时音视频,还要进一步考虑 WebRTC。
这版的核心结论就是:不是“AI 必须用 SSE”,而是“AI 文本对话的通信模型刚好非常适合 SSE”。