前言
- 维护心跳和断线重连,代码越来越复杂;(参考:websocket 的心跳机制你知道几种)
- 服务端和代理层要支持 WebSocket 协议,配置麻烦;
- 实际需求只是报表看板、通知推送,根本用不上复杂的双向通信。
于是,我们团队开始思考:
有没有一种更简单的方式,只要"服务端推数据给客户端",不需要那么多额外的心智负担?
答案就是 ------ SSE(Server-Sent Events) 。
🔍 什么是 SSE?
SSE,全称 Server-Sent Events ,是一种基于 HTTP 长连接 的单向通信机制。
- 浏览器通过
EventSource
发起一个普通的 HTTP 请求 - 服务器不断往这个连接推送数据(
text/event-stream
格式) - 浏览器原生支持接收和处理消息
- 内置自动重连:如果连接断开(例如网络波动),浏览器会自动尝试重新连接,不需要手动写心跳逻辑
换句话说,SSE 就是一个开箱即用的"服务器 → 客户端推送管道"。
⚔️ SSE vs WebSocket
特性 | SSE | WebSocket |
---|---|---|
通信方向 | 单向(服务端 → 客户端) | 全双工(客户端 ↔ 服务端) |
协议 | HTTP/1.1 长连接 | 独立的 WebSocket 协议 |
断线重连 | ✅ 内置自动重连 | ❌ 需要手动实现心跳与重连 |
数据格式 | 文本(UTF-8) | 文本 & 二进制 |
浏览器支持 | 现代浏览器原生支持 | 广泛支持 |
典型场景 | 报表、看板、日志、通知流 | 聊天、游戏、协同编辑、高频交互 |
一句话总结:
- 只需要"看"的场景 → 用 SSE
- 既要"看"又要"说"的场景 → 用 WebSocket
📌 使用场景对比
✅ SSE 适合
- 报表/大屏看板实时数据刷新
- 股票、天气、日志流
- 系统通知、消息提醒
- IoT 数据上报
✅ WebSocket 适合
- 聊天、IM 系统
- 协同编辑(Google Docs 类场景)
- 游戏、实时白板
- 高频交互、需要双向通信的应用
🛠️ 实战示例
前端:使用 SSE
js
// 前端 SSE 示例
const eventSource = new EventSource('/sse');
eventSource.onmessage = (event) => {
console.log('收到数据:', event.data);
// 更新到报表看板
};
eventSource.onerror = (err) => {
console.error('SSE 错误:', err);
};
后端(Node.js Express)
js
import express from 'express';
const app = express();
app.get('/sse', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
let count = 0;
const timer = setInterval(() => {
count++;
res.write(`data: ${JSON.stringify({ time: new Date(), value: count })}\n\n`);
}, 2000);
req.on('close', () => clearInterval(timer));
});
app.listen(3000, () => console.log('SSE 服务运行在 http://localhost:3000'));
效果
- 浏览器每隔 2 秒自动收到一条数据
- 无需轮询,也不用自己写心跳/重连逻辑
- 断网后,SSE 会自动重连,带着
Last-Event-ID
从断点继续
⚡ 踩坑点与优化
-
Nginx 代理 SSE
要关闭 buffering,否则数据会被攒起来再发。
nginxlocation /sse { proxy_pass http://127.0.0.1:3000; proxy_set_header Connection ''; chunked_transfer_encoding off; proxy_buffering off; proxy_cache off; proxy_set_header Cache-Control 'no-cache'; }
-
浏览器兼容性
- IE 不支持,需要 polyfill
- Safari 在弱网环境下可能掉线,但会自动重连
-
连接数限制
- Chrome/Firefox 对同一域名的 HTTP 长连接有限制(一般 6 个左右)
- 多 tab 同时订阅 SSE 时,建议使用
BroadcastChannel
或SharedWorker
共享连接
🎯 总结
- WebSocket 功能全面,但需要维护心跳、断线重连,适合高频交互
- SSE 简单轻量,自带自动重连,适合单向推送
在我们的项目里,原本用 WebSocket 做报表看板,结果发现:
- 双向通信完全用不上
- 重连逻辑写了一堆,反而容易出 bug
- Nginx 配置 WebSocket 还要单独适配
于是,果断切到 SSE,不仅减少了代码量,还让整个链路更稳定。
👉 技术选型的关键是匹配业务需求:
- 如果只是推数据,SSE 足够优雅。
- 如果需要互动交流,WebSocket 还是唯一选择。