AI大模型的回答推送?SSE技术了解一下?
SSE 是什么?
SSE(Server-Sent Events)是一种基于 HTTP 协议的允许服务器向客户端推送实时数据的技术,它允许服务器通过一个持久化的 HTTP 连接,持续向客户端发送事件数据,当前常用于 AI大模型的回答推送。
为什么会有 SSE?
https://html.spec.whatwg.org/multipage/server-sent-events.html
Server-Sent Events(SSE) 是 HTML5 标准(2009 年)提出的实时通信协议,旨在解决传统轮询技术的效率瓶颈。
-
前身技术:早期的实时数据更新依赖于 轮询(Polling) 或 长轮询(Long-Polling),但这些方案会引发高延迟和资源浪费(例如客户端每秒发送 HTTP 请求)。
-
标准化进程: W3C 在 HTML5 规范中明确定义 SSE 协议,通过
EventSourceAPI 实现浏览器原生支持,为服务器主动推送数据提供标准化方案。
SSE 如何实现数据推送?
严格地说,HTTP 协议无法做到服务器主动推送信息,但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息(streaming),也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来,客户端不会关闭连接,会一直等着服务器发过来的新的数据流。总结如下:
-
SSE 使用 HTTP 建立长连接(通常是 HTTP/1.1 的
Connection: keep-alive)保持 TCP 连接不断开。 -
服务器返回
Content-Type: text/event-stream,告诉浏览器这是一个事件流。 -
然后服务器不断通过 HTTP 响应流(stream)发送事件数据,每条事件以特定格式推送。
-
浏览器的
EventSourceAPI 会自动解析这些流式数据,并触发对应的事件回调。
SSE 发送数据格式说明
一般来说,SSE 发送的数据格式长这样:
id: 123\n # 消息唯一标识(断线重连时通过 `Last-Event-ID` 发送)
event: temperature\n # 事件类型(默认 `message`)
data: {"value": 25.6}\n # 数据内容(可多行)
retry: 3000\n\n # 重试间隔(毫秒)
-
每个字段行以
\n结束,消息以\n\n结束。 -
id:事件 ID(可选),浏览器会用它做断线重连时的Last-Event-ID。 -
event:事件类型(可选),用于客户端区分不同事件。 -
data:事件的主要数据内容(必须),可以有多行,每行都以data:开头。 -
retry:重连时间(可选),告诉浏览器断线重连的时间(毫秒)。
只包含data字段
data: 服务器状态正常\n data: 服务器状态正常\n\n
多行数据 + 全部字段
id: 305\n event: update\n data: 数据库已更新\n data: 请检查最新记录\n retry: 5000\n\n
只包含 event + data
event: start_stream\n data: 开始数据\n\n
SSE 代码实现
服务端
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@RestController
public class SSEController {
private static final String X_ACCEL_BUFFERING = "X-Accel-Buffering";
private static final String X_ACCEL_NO_BUFFERING = "no";
private static final String CACHE_CONTROL = "Cache-Control";
private static final String NO_CACHE = "no-cache";
private static final Integer BUFFER_SIZE = 0;
@GetMapping(path = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter streamEvents(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
SseEmitter emitter = new SseEmitter();
// 实时流
// 禁用代理缓冲
httpServletResponse.setHeader(X_ACCEL_BUFFERING, X_ACCEL_NO_BUFFERING);
// 禁用客户端缓存
httpServletResponse.setHeader(CACHE_CONTROL, NO_CACHE);
// 禁用响应缓冲
httpServletResponse.setBufferSize(BUFFER_SIZE);
// 模拟异步发送事件
new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
emitter.send("send Message " + i);
Thread.sleep(1000);
}
// 发送结束事件
emitter.send(SseEmitter.event().name("end").data("Stream finished"));
emitter.complete(); // 关闭连接
} catch (Exception e) {
emitter.completeWithError(e);
}
}).start();
return emitter;
}
}
测试结果:

注意事项
因为 SSE 是基于响应流返回数据,需要确保 HTTP 响应流不被拦截、不被提前处理或者关闭。
SSE、SOCKET对比
|
特性 |
WebSocket(Socket) |
SSE(Server-Sent Events) |
|---|---|---|
|
通信模式 |
双向通信(全双工) |
单向通信(服务器 → 客户端) |
|
协议 |
独立协议(ws/wss) |
HTTP/1.1 长连接 |
|
数据格式 |
文本 & 二进制 |
仅文本(UTF-8) |
|
连接方式 |
需 HTTP Upgrade 握手 |
直接使用 HTTP 长连接 |
|
延迟 |
低 |
低 |
|
自动重连 |
需手动实现 |
浏览器原生支持 |
|
适用场景 |
聊天、游戏、实时协作 |
实时通知、数据流推送 |
SSE 和 WebSocket 功能类似,都可以用来实现服务器向客户端实时推送数据的技术,怎么选择?
-
如果只需要服务器向客户端推送简单的通知、事件更新等,而不需要进行双向通信,选择 SSE。
-
如果需要实现实时通信,例如在线聊天、协作编辑等,选择 WebSocket。
-
如果应用可能在一些不支持 WebSocket 的环境中运行,或者需要考虑到更广泛的浏览器兼容性,选择 SSE。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)