SSE Server-Sent Events 工作机制
SSE(Server-Sent Events,服务端推送事件)是一种基于 HTTP 协议,允许服务端单向向客户端持续发送数据的技术。它最初在 HTML5 中被标准化,通常与前端的 EventSource 接口搭配使用。相较于 WebSocket 双向通信而言,SSE 更适合“服务器持续向客户端推送更新”这一单向场景,使用起来更简单。
以下从工作原理和特点两方面进行介绍:
————————————————
1. 工作原理
————————————————
1) 客户端发起请求
• 客户端(通常是浏览器)通过 JavaScript 中的 EventSource 对象向服务端发起一个长连接请求,这个请求的路径一般会返回特定的 MIME 类型:text/event-stream。
• 请求示例(JavaScript 端):
const eventSource = new EventSource('https://example.com/sse');
eventSource.onmessage = function(event) {
console.log('接收到数据:', event.data);
};
2) 服务端返回流式数据
• 服务端在收到此请求后,保持连接不断开,使用 HTTP Chunked 传输或类似机制,以 text/event-stream 格式持续返回数据。
• 在 SSE 协议中,服务端发送的数据格式通常如下:
data: 这是第一条消息
data: 这是第二条消息
(空行分隔每条消息)
• 每条消息可包含以下字段:
• data: 消息体。
• id: 消息编号,可在服务器到客户端的数据流中标识当前消息。
• event: 自定义事件类型,用于客户端注册不同类型的事件回调。
• retry: 如果连接断开,客户端应该在多少毫秒后尝试重连。
3) 自动重连
• SSE 标准规定,如果连接意外断开,浏览器会自动重试连接,并携带最后接收的 event id(若有)告诉服务器继续发送后续消息,不用重复从头开始。
• 这种特性让 SSE 在网络波动的情况下也能方便地保持数据流的连续性。
4) 单向通信
• SSE 最大的特点之一是服务器→客户端的单向通信,这意味着客户端不能直接通过该连接发送数据到服务器。
• 如果需要双向通信,可以使用 WebSocket;如果只是服务端推送,SSE 即可满足需求。
————————————————
2. 主要特点
————————————————
1) 使用简单:
• SSE 使用的依旧是普通的 HTTP 通道,请求和响应都符合 HTTP 协议,不需要额外建立特殊协议或做过多处理。
2) 浏览器原生支持:
• 主流现代浏览器(Chrome、Firefox、Safari 等)通过 EventSource 接口直接支持 SSE,因此前端使用非常方便。
3) 自动重连和消息定位:
• 浏览器若断开,会自动重试连接;可通过 id 字段标识已发送的消息,保证数据不丢失。
4) 单向推送:
• 只需在服务器端持续输出流数据,不需要复杂的“双工”逻辑,适合简单的实时信息推送场景,例如股票行情、新闻推送、社交媒体动态、进度更新等。
5) 相比 WebSocket:
• WebSocket:基于 TCP 的全双工连接,适用于需要实时双向交互的复杂场景。
• SSE:基于 HTTP 的单向推送,适用于简单的服务器→客户端持续推送,且在消息重连、轻量级部署方面较为便捷。
————————————————
3. 一个简单示例
————————————————
• 前端(客户端)使用:
const eventSource = new EventSource('/stream');
eventSource.onmessage = function(e) {
console.log('Received message:', e.data);
};
eventSource.onerror = function(e) {
console.error('连接出错:', e);
};
• 后端(以 Node.js 为例):
const http = require('http');
http.createServer((req, res) => {
// 设置 response 头
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
// 每隔一秒推送一条消息
let counter = 0;
const timer = setInterval(() => {
counter++;
res.write(`data: 这是第 ${counter} 条消息\n\n`);
}, 1000);
// 若客户端断开连接,清理定时器
req.on('close', () => {
clearInterval(timer);
console.log('客户端连接已断开!');
});
}).listen(3000);
————————————————
4. 使用场景
————————————————
• 实时推送通知:新闻、社交媒体信息、聊天室系统的只读广播等。
• 实时更新数据:比如股票行情、比赛比分更新、进度条等。
• 服务器主动推送事件:如监控系统、报警系统的实时警报推送。
————————————————
5. 总结
————————————————
SSE(Server-Sent Events)通过建立一个持续开放的 HTTP 连接,允许服务端向客户端推送数据,并且具有自动断线重连等机制。它的重点在“单向推送”,实现逻辑简单、部署方便、浏览器原生支持。与需要双向通信的 WebSocket 相比,SSE 更适合用于轻量化的实时推送场景。