SSE适合服务端单向推送场景,如日志流、通知和状态更新;其核心是HTTP长连接,服务端按text/event-stream格式输出data:等字段事件流,客户端用EventSource自动重连监听。

SSE(Server-Sent Events)是一种基于 HTTP 的单向实时通信机制,服务器主动向浏览器推送事件,适合日志流、通知、状态更新等场景。实现关键在于服务端按规范输出特定格式的响应流,客户端用 EventSource 订阅并监听。
服务端:按 SSE 格式持续输出事件流
服务器需设置正确的响应头,并保持连接打开,以文本流方式发送事件。每条事件必须以 data: 开头,可选 event:、id: 和 retry: 字段,每条消息以双换行符分隔。
- 响应头必须包含
Content-Type: text/event-stream和Cache-Control: no-cache - 避免响应体被缓冲(如 Node.js 中调用
res.flush()或设置res.write后立即刷新) - 每条事件末尾加两个换行符(
\n\n),否则浏览器不会触发message事件 - 示例(Express):
app.get('/events', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
// 模拟每秒推送一条数据
const interval = setInterval(() => {
const data = JSON.stringify({ time: new Date().toISOString() });
res.write(`data: ${data}\n\n`);
}, 1000);
req.on('close', () => {
clearInterval(interval);
res.end();
});
});客户端:用 EventSource 建立连接并监听事件
EventSource 是浏览器原生 API,自动重连(默认 3 秒),支持 message、自定义事件名和 error 监听。
- 创建实例时传入 SSE 接口地址,自动发起 GET 请求
- 监听
message事件接收无event:字段的默认事件;用addEventListener('xxx')接收自定义事件 - 可通过
eventSource.close()主动关闭连接 - 注意跨域问题:若接口跨域,服务端需添加
Access-Control-Allow-Origin响应头
const eventSource = new EventSource('/events');
eventSource.onmessage = (e) => {
console.log('收到消息:', JSON.parse(e.data));
};
eventSource.addEventListener('update', (e) => {
console.log('自定义 update 事件:', e.data);
});
eventSource.onerror = (err) => {
console.error('SSE 连接出错', err);
};常见问题与注意事项
SSE 看似简单,但实际使用中容易踩坑,尤其在连接稳定性、数据解析和错误处理上。
- 服务端不要结束响应(
res.end()),除非明确要断开;否则连接会关闭,触发浏览器重连 - 每条
data:后必须有换行,多条数据可合并为一个data:行,用\n分隔(浏览器会拼接后触发一次message) - 若需传递 ID,写成
id: 123\n,浏览器会在重连时通过Last-Event-ID头带回去,服务端可据此恢复上下文 - 移动端部分 WebView(如旧版 iOS UIWebView)不支持 SSE,需降级方案(如轮询或 WebSocket)
对比 WebSocket 和轮询的适用场景
SSE 不是万能替代品,选择取决于业务需求:
- 只读场景(如股票行情、系统监控)优先用 SSE:轻量、兼容性好、自动重连、无需额外库
- 需要双向通信(如聊天、协作编辑)必须用 WebSocket
- 低频、简单状态同步可用定时轮询,但延迟高、请求冗余,不推荐高频使用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











