SSE(Server Sent Event) 一种轻量化服务器推送方案
约 1145 字大约 4 分钟
2026-08-11
什么是SSE协议
SSE协议,是HTML5标准之一,允许服务器通过单一HTTP连接向客户端单向推送文本事件。 SSE的出现是基于HTTP 长连接的。服务器要实现持续推送消息给客户端,就必须保持TCP连接不会在一次HTTP响应后中断。 SSE协议就复用了HTTP长连接的特性,当客户端向服务器中声明使用SSE协议的接口发起请求时, 服务器此后的返回内容,都会是一段带有特殊响应头以及SSE消息格式的响应体的HTTP响应报文。 同时服务端可以复用这一个HTTP连接,不断的向其中发送HTTP响应。 也就是说,所谓的SSE协议,就是建立在HTTP 长连接特性之上的带有特殊响应体消息格式的消息协议。
SSE协议的建立过程
- 客户端向服务器一个支持返回SSE消息的接口发送普通的HTTP请求报文,在这段时间,TCP三次握手建立,HTTPS安全隧道也被建立起来。
- 服务器在收到客户端消息后,会返回带有特殊消息头的响应报文
Content-Type: text/event-stream代表后续返回的响应体都是SSE消息格式Cache-Control: no-cache禁止缓存这些消息Connection: keep-alive保持HTTP长连接,不要收到一次响应后断开连接- 更重要的是响应头不会携带Content-length字段,也就是说消息没有固定的长度,接下来服务器还会推送消息
- 在客户端眼里,首先如果它没有调用支持SSE消息格式解析的函数,而是单纯的fetch,那么客户端也就不具备持续接收消息的能力,只能在服务端传递完全部消息时通过回调函数进行处理
- 如果它有支持SSE消息格式解析,支持分片传输,那么就可以定义一个onChunkReceived回调函数,每当服务端发送来一段SSE消息时都会触发这个回调函数,对SSE消息进行解析,执行客户端内部定义的逻辑
SSE协议消息的格式是什么
对于每条SSE消息,一般而言都是以event + data: 行组成,\n\n 空行进行区分每个SSE消息
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
event: thinking
data: {"type":"thinking","requestId":"...","data":"我先分析一下..."}
event: message
data: {"type":"message","requestId":"...","data":"找到以下信息"}
event: done
data: {"type":"done","requestId":"...","data":{"promptTokens":120,...}}可以看到每条消息就是一个服务器推送的事件。 事件由事件名称和事件数据组成。利用SSE协议,服务器和客户端可以双方协定一些业务事件类。当服务器推送特定的业务事件时,客户端就可以执行相关的逻辑。
Spring 对 SSE 的支持
Spring Framework提供了org.springframework.http.codec.ServerSentEvent<T>,同时配合Project Reactor响应式编程的Flux对象,可以轻松实现在Tomcat服务器上维持长连接并推送异步事件。
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import reactor.core.publisher.Flux;
@PostMapping(value = "/agent/run", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<MyEvent>> agentRun(...) { ... }produces = MediaType.TEXT_EVENT_STREAM_VALUE告诉Spring框架,这是一个返回SSE信息流的接口,对于返回的数据要使用特定的编码器以及设置对应的响应头ServerSentEvent.builder()可以设置一条SSE消息的event和data等字段- Flux是实现了流式数据编排的响应式基础类,接口返回这个响应式对象,Tomcat就会释放工作线程交由MVC的异步线程池进行数据的返回,因而不会出现因为长连接阻塞Tomcat工作线程的问题
为什么AI大模型一般采用SSE协议进行传输
- 业务匹配 :大模型是逐Token生成,属于用户发送一次请求,服务端单向持续推送数据,SSE刚好满足这种需求
- 基于HTTP: 无需协议升级,直接复用原有基于HTTP的网关,鉴权等基础设施,网络兼容性强
- 内存占用低 : 在服务器中不用向WebSocket需要维护用户的会话信息,内存占用仅为一个TCP连接,搭配IO多路复用可以支持更多的连接数