为什么所有 AI 对话都在用 SSE而不是WebSocket
我们平时在用豆包、deepseek时,不难发现AI的回答都是一个字一个字蹦出来的,也就是大家常说的打字机效果。这种效果是很好的,如果让大家输入一个问题,等半天AI才“啪”地一下输出整段结果,大家一定会骂街吧哈哈哈。
那这种流式输出的效果是怎么输出的呢?这就是我们今天要讲的SSE。
但偏偏所有主流 AI 对话项目,全都放弃了 WebSocket,清一色用 SSE 实现流式输出。这到底是为什么?
一句话总结:SSE最合适。
一、SSE 到底是什么?
SSE 全称 Server-Sent Events,翻译过来就是服务器推送事件,它是一个基于原生 HTTP 协议的单向长连接技术。
SSE 的工作逻辑特别简单,全程就三步:
前端发起一次普通的 HTTP 请求,不用任何特殊协议升级;
服务端收到请求后,不立即返回结果、不关闭连接,一直保持连接状态;
服务端有数据后,源源不断主动推给前端(这就实现了打字机效果),前端只负责接收,不用重复发请求。
简单总结核心特点:基于普通 HTTP、只支持服务端推客户端、长连接保活、天生适配流式数据。
这样看似功能单一,但刚好踩中 AI 对话的所有需求点,因为对用户友好。
二、为什么 AI 必须做「流式输出」?
想要理解 SSE 的优势,首先得搞懂大模型的回答逻辑。
大语言模型不是一次性生成完整答案的,它是逐 Token逐步生成的,生成一个字、输出一个字,全程是一个持续的过程。
如果我们用传统的 HTTP 一次性请求模式,就会出现一个很尴尬的问题:用户发送提问后,页面彻底空白,只能干等,短则两三秒,长则十几秒。普通用户根本不知道是网络卡了、页面崩了,还是模型在生成回答,大概率要骂街,随后直接退出再也不用这家产品。
而流式输出完美解决了这个体验痛点:
不用等全部答案生成完毕,生成一个字就展示一个字,实时的打字效果会给用户一种“AI 正在实时思考作答”的直观感受。虽然整体回答的总耗时没变,但用户的等待感知大幅降低,交互体验直接拉满。
三、SSE vs WebSocket
那大家可能会有疑惑了:实时数据推送不都用 WebSocket 吗?这家伙的功能更强,为什么 AI 对话不用?
其实行业选型的核心逻辑从来不是谁功能更强,而是看谁更适配场景、更省心、成本更低。在纯 AI 流式对话场景中,WebSocket 属于典型的功能过剩、负担超标,而 SSE 是精准适配。
1. 两者优劣比较
SSE 的核心优势
部署零门槛,兼容性拉满:基于标准 HTTP/HTTPS 协议,不用改协议、不用特殊配置,Nginx、CDN、防火墙、反向代理全部原生兼容,线上部署几乎零踩坑,新手也能快速上线。
自带断线重连,不用手写逻辑:遇到网络波动、页面休眠、临时断网,浏览器会自动重试连接,不用开发者手动写心跳保活、断线重连、异常重置代码,大幅减少bug。
轻量低耗,性能更优:没有复杂的握手协商、消息帧解析、心跳检测机制,连接开销极低。高并发场景下,服务器承载压力远小于 WebSocket,稳定性更好。
场景高度匹配,无冗余功能:AI 对话固定逻辑是「前端提问一次,服务端持续返回答案」,全程不需要前端实时传数据,SSE 的单向推送能力完全够用,没有任何功能浪费。
WebSocket 的核心短板
协议复杂、开发成本高:需要手动处理握手验证、心跳保活、消息分片、断线重连、连接销毁等一系列逻辑,代码量大幅增加,bug 概率翻倍。
线上兼容性一般:部分防火墙、代理服务会拦截 WebSocket 特殊协议,生产环境容易出现莫名断连、适配失败的问题。
功能严重冗余:双向通信的能力在 AI 对话中完全用不上,为了用不到的功能承担更高的开发、运维、性能成本,完全得不偿失。
2. 核心参数对比表
对比维度 | SSE(服务器推送事件) | WebSocket |
|---|---|---|
通信方式 | 单向通信(服务端→客户端) | 双向实时通信 |
底层协议 | 基于标准 HTTP 协议 | 独立 WS 协议,需协议升级 |
断线重连 | 浏览器原生自动重连 | 需开发者手动实现 |
性能开销 | 轻量低耗,高并发友好 | 开销较高,需维护心跳 |
适用场景 | 消息推送、AI流式输出、日志实时打印 | 实时通话、协同编辑、游戏、直播互动 |
一句话总结:需要双向实时交互选 WebSocket,单纯做 AI 流式对话,SSE 是性价比、稳定性、开发成本最优解。
四、简单实现Java项目接入SSE
后端接口代码
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.io.IOException; @RestController @RequestMapping("/sse") public class SseController { // 创建 SSE 连接,超时时间设为 30 分钟 @GetMapping(value = "/connect", produces = "text/event-stream;charset=UTF-8") public SseEmitter connect() { // 设置超时时间 30分钟 SseEmitter emitter = new SseEmitter(30 * 60 * 1000L); // 连接成功后发送一条欢迎消息 try { emitter.send(SseEmitter.event().name("message").data("SSE 连接成功!")); } catch (IOException e) { emitter.completeWithError(e); } return emitter; } }前端测试代码(HTML)
<!DOCTYPE html> <html> <body> <h3>SSE 实时消息</h3> <div id="msg"></div> <script> // 连接后端 SSE const source = new EventSource("http://localhost:8080/sse/connect"); // 接收消息 source.onmessage = function (event) { document.getElementById("msg").innerHTML += event.data + "<br>"; }; // 连接打开 source.onopen = function () { console.log("SSE 连接已建立"); }; // 异常 source.onerror = function () { console.log("连接异常"); }; </script> </body> </html>五、总结
目前 SSE 已经是 AI 大模型对话的行业通用标准,没有之一。OpenAI 官方流式接口、国内豆包、通义千问、Kimi 等所有主流 AI 产品,全部基于 SSE 实现流式输出。
技术选型从不选最强的,只选最合适的。
