文章首发于公众号:BiggerBoy
原文链接:WebSocket之外,SSE协议为何被大厂悄悄采用?)
SSE(Server-Sent Events,服务器发送事件)是一种基于 HTTP 的协议,允许服务器向客户端(如浏览器)主动推送实时数据。它是 HTML5 规范的一部分,旨在简化单向实时通信的实现。
核心特性
- 单向通信
SSE 仅支持服务器到客户端的单向数据推送,客户端通过普通 HTTP 请求建立连接后,服务器可随时发送数据。 - 基于 HTTP
使用标准的 HTTP 协议,无需额外的协议(如 WebSocket),兼容现有基础设施(如身份验证、代理)。 - 长连接(Long Polling)
客户端通过一个持久的 HTTP 连接接收数据流,服务器通过该连接持续发送更新。 - 自动重连
客户端内置断线重连机制,若连接中断会自动尝试重新连接。 轻量数据格式
数据以纯文本流格式(text/event-stream
)传输,每条消息可包含以下字段:data
: 消息内容(必填,支持多行)。event
: 自定义事件类型(可选,用于客户端区分不同事件)。id
: 消息的唯一标识(可选,用于断线后恢复)。retry
: 重连时间间隔(毫秒,可选)。
- *
工作原理
客户端
使用 JavaScript 的EventSource
API 发起请求:const eventSource = new EventSource('/sse-endpoint'); eventSource.onmessage = (event) => { console.log('收到数据:', event.data); }; eventSource.addEventListener('customEvent', (event) => { console.log('自定义事件:', event.data); });
服务器
响应需设置 HTTP 头:通过流(Stream)持续发送数据,格式示例:
event: customEvent data: {"status": "update", "value": 42} id: 123 retry: 3000 data: 这是一条普通消息\n多行内容
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
- *
与 WebSocket 的对比
特性 | SSE | WebSocket |
---|---|---|
方向 | 单向(服务器→客户端) | 双向全双工 |
协议 | HTTP | 独立的 ws:// 或 wss:// 协议 |
复杂度 | 简单,无需额外库 | 需处理握手、帧协议等 |
断线恢复 | 自动重连,支持id 恢复 | 需手动实现 |
适用场景 | 实时通知、股票行情、日志流 | 聊天、游戏等双向交互 |
使用场景
- 实时数据推送(如新闻、股价、天气)。
- 进度更新(如文件上传/处理进度)。
- 日志流监控。
- 无需双向交互的轻量级实时应用(生成式AI,比如DeepSeek回复的内容)。
- *
优点
- 简单易用:基于 HTTP,无需复杂协议实现。
- 兼容性:现代浏览器广泛支持(IE 除外,可通过 Polyfill 兼容)。
- 自动重连:内置断线恢复机制。
- 低开销:文本格式数据轻量,适合高频小数据量场景。
- *
缺点
- 单向通信:无法从客户端向服务器发送数据(需配合其他 HTTP 请求)。
- 文本格式限制:二进制数据传输需编码(如 Base64)。
- 连接数限制:浏览器对同一域的 SSE 连接数有限制(通常 6 个)。
- *
示例代码
客户端(浏览器) :
const eventSource = new EventSource('/updates');
eventSource.onmessage = (e) => {
console.log('新消息:', e.data);
};
eventSource.onerror = () => {
console.error('连接错误');
};
服务器(Node.js) :
const http = require('http');
http.createServer((req, res) => {
if (req.url === '/updates') {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
let id = 0;
setInterval(() => {
res.write(`data: ${JSON.stringify({ time: Date.now() })}\n\n`);
id++;
}, 1000);
}
}).listen(3000);
注意事项
- 确保服务器不支持压缩(如 gzip),否则可能中断流传输。
- 避免在消息中使用单行结束符(
\n
),需使用双换行符(\n\n
)分隔消息。 - 对于敏感数据,需使用 HTTPS 防止中间人攻击。
SSE 是替代传统轮询(Polling)和长轮询(Long Polling)的高效方案,适用于需要服务器主动推送的实时场景。
关注【BiggerBoy】公众号,获取更多技术干货!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。