为什么所有 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 实现流式输出。
技术选型从不选最强的,只选最合适的。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)