文章首发于公众号:BiggerBoy

原文链接:WebSocket之外,SSE协议为何被大厂悄悄采用?)

SSE(Server-Sent Events,服务器发送事件)是一种基于 HTTP 的协议,允许服务器向客户端(如浏览器)主动推送实时数据。它是 HTML5 规范的一部分,旨在简化单向实时通信的实现。


核心特性

  1. 单向通信
    SSE 仅支持服务器到客户端的单向数据推送,客户端通过普通 HTTP 请求建立连接后,服务器可随时发送数据。
  2. 基于 HTTP
    使用标准的 HTTP 协议,无需额外的协议(如 WebSocket),兼容现有基础设施(如身份验证、代理)。
  3. 长连接(Long Polling)
    客户端通过一个持久的 HTTP 连接接收数据流,服务器通过该连接持续发送更新。
  4. 自动重连
    客户端内置断线重连机制,若连接中断会自动尝试重新连接。
  5. 轻量数据格式
    数据以纯文本流格式(text/event-stream)传输,每条消息可包含以下字段:

    • data: 消息内容(必填,支持多行)。
    • event: 自定义事件类型(可选,用于客户端区分不同事件)。
    • id: 消息的唯一标识(可选,用于断线后恢复)。
    • retry: 重连时间间隔(毫秒,可选)。
    • *

工作原理

  1. 客户端
    使用 JavaScript 的 EventSource API 发起请求:

    const eventSource = new EventSource('/sse-endpoint');
    eventSource.onmessage = (event) => {
      console.log('收到数据:', event.data);
    };
    eventSource.addEventListener('customEvent', (event) => {
      console.log('自定义事件:', event.data);
    });
  2. 服务器
    响应需设置 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 的对比

特性SSEWebSocket
方向单向(服务器→客户端)双向全双工
协议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】公众号,获取更多技术干货!

在这里插入图片描述


biggerboy
81 声望0 粉丝