从 WebSocket 转向 SSE:轻量实时推送的另一种选择

前言

  • 维护心跳和断线重连,代码越来越复杂;(参考: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 从断点继续

⚡ 踩坑点与优化

  1. Nginx 代理 SSE

    要关闭 buffering,否则数据会被攒起来再发。

    nginx 复制代码
    location /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';
    }
  2. 浏览器兼容性

    • IE 不支持,需要 polyfill
    • Safari 在弱网环境下可能掉线,但会自动重连
  3. 连接数限制

    • Chrome/Firefox 对同一域名的 HTTP 长连接有限制(一般 6 个左右)
    • 多 tab 同时订阅 SSE 时,建议使用 BroadcastChannelSharedWorker 共享连接

🎯 总结

  • WebSocket 功能全面,但需要维护心跳、断线重连,适合高频交互
  • SSE 简单轻量,自带自动重连,适合单向推送

在我们的项目里,原本用 WebSocket 做报表看板,结果发现:

  • 双向通信完全用不上
  • 重连逻辑写了一堆,反而容易出 bug
  • Nginx 配置 WebSocket 还要单独适配

于是,果断切到 SSE,不仅减少了代码量,还让整个链路更稳定。

👉 技术选型的关键是匹配业务需求:

  • 如果只是推数据,SSE 足够优雅。
  • 如果需要互动交流,WebSocket 还是唯一选择。
相关推荐
子兮曰6 小时前
🚀 图片加载速度提升300%!Vue/React项目WebP兼容方案大揭秘
前端·vue.js·react.js
郭俊强6 小时前
nestjs 阿里云服务端签名
前端·网络·阿里云
wordbaby6 小时前
用 useReducer 优雅管理 React 状态
前端·react.js
不爱说话郭德纲6 小时前
还记得第一次遇到内存泄漏的场景嘛?
前端·面试·性能优化
南囝coding6 小时前
2025 最新!独立开发者穷鬼套餐
前端·后端
LaiYoung_6 小时前
前端国际化适配提速 90%!这款 JS 脚本 CLI 工具,自动提中文、分模块、做替换,比 AI 更稳定
前端·javascript·人工智能
JohnYan6 小时前
工作笔记-微信消息接收机制与实现
javascript·后端·微信
低代码布道师6 小时前
CSS 伪类与伪元素:深度解析
前端·css