文章目录
-
- [1. 工作原理:一个永不结束的 HTTP 响应](#1. 工作原理:一个永不结束的 HTTP 响应)
-
- [1.1 建立流程](#1.1 建立流程)
- [1.2 SSE 协议数据格式](#1.2 SSE 协议数据格式)
- [2. 核心特点](#2. 核心特点)
-
- [2.1 优点](#2.1 优点)
- [2.2 缺点](#2.2 缺点)
- [3. 重连机制详解](#3. 重连机制详解)
-
- [3.1 默认重连行为](#3.1 默认重连行为)
- [3.2 服务端控制重连间隔](#3.2 服务端控制重连间隔)
- [4. 断点续传实现](#4. 断点续传实现)
-
- [4.1 工作原理](#4.1 工作原理)
- [5. 与 WebSocket 的选型对比](#5. 与 WebSocket 的选型对比)
-
- [5.1 对比表格](#5.1 对比表格)
- [5.2 选型建议](#5.2 选型建议)
SSE (Server-Sent Events) 是一种基于 标准 HTTP 协议 的服务器主动推送技术。它允许服务器通过一个 长连接 持续向客户端发送数据流,客户端使用浏览器内置的 EventSource API 即可接收。
SSE 核心原理:
客户端发起一个普通的 HTTP 请求,服务端收到后不关闭连接 ,而是将响应头 Content-Type 设置为 text/event-stream。每当有新数据时,服务端按协议格式写入响应流,客户端通过监听事件实时接收。连接保持打开状态,直到任意一方主动关闭或网络中断
SSE 是单向的:服务器 → 客户端。客户端若需发送数据,需要另外发起一个普通的 HTTP 请求
1. 工作原理:一个永不结束的 HTTP 响应
SSE 的建立非常简单,没有复杂的握手升级过程:
1.1 建立流程
- 客户端发起请求 :
new EventSource('/api/stream') - 服务器响应 :返回状态码
200,并设置以下响应头Content-Type: text/event-streamCache-Control: no-cacheConnection: keep-alive
- 数据推送:服务端保持连接打开,按 SSE 协议格式不断写入数据块
- 连接关闭:服务端或客户端主动关闭,或网络断开
1.2 SSE 协议数据格式
每条消息由若干字段组成,字段之间用 \n 分隔,消息之间用 两个换行符 \n\n 结尾。
字段说明:
| 字段 | 含义 | 是否必须 | 说明 |
|---|---|---|---|
event: |
事件类型 | 否 | 默认触发 onmessage,可自定义如 update、error |
data: |
数据内容 | 是 | 可多行,客户端会自动拼接 |
id: |
消息唯一标识 | 否 | 用于断线续传,重连时会带到 Last-Event-ID 头 |
retry: |
重连等待时间(ms) | 否 | 覆盖浏览器默认的 3 秒重连间隔 |
示例消息:
event: message
id: 1001
data: {"type": "text", "content": "Hello"}
data: 这是第二行内容,会与上一行拼接
注意:最后必须有 两个换行符 表示消息结束。
2. 核心特点
2.1 优点
| 特点 | 说明 |
|---|---|
| 简单轻量 | 基于标准 HTTP,无需特殊协议,任何 Web 服务器都能支持 |
| 自动重连 | 浏览器内置 EventSource 会在连接断开后自动重连,无需手动实现 |
| 断点续传 | 通过 id 字段和 Last-Event-ID 机制,服务端可恢复丢失的消息 |
| 低开销 | 相比 WebSocket,没有复杂的握手和帧协议,Header 开销极小 |
| 天然跨域友好 | 支持 CORS,可通过 withCredentials 配置携带凭证 |
| 调试方便 | 本质是 HTTP 请求,可在浏览器 DevTools Network 面板直接查看 |
2.2 缺点
| 缺点 | 说明 |
|---|---|
| 单向通信 | 只能服务器推送给客户端,客户端需要另外发 HTTP 请求上传数据 |
| 连接数限制 | HTTP/1.1 下浏览器对同一域名的长连接数有限制(通常 6 个) |
| 二进制支持弱 | 原生只支持文本(UTF-8),二进制需用 Base64 编码传输 |
| IE 不支持 | IE 全系列不支持,Edge 及所有现代浏览器均已支持 |
| 服务端需维护长连接 | 每个连接都占用服务端资源,高并发时需注意 |
3. 重连机制详解
SSE 最大的优势之一就是浏览器内置了自动重连,无需手动实现复杂的重试逻辑。
3.1 默认重连行为
- 连接断开后,浏览器会等待 3 秒 后自动尝试重连
- 重连时会自动携带上次收到的最后一条消息的
id,放在Last-Event-ID请求头中 - 服务端可根据这个 ID 决定从哪个位置开始续传
- 重连会无限进行下去,直到连接成功或客户端主动关闭
3.2 服务端控制重连间隔
服务端通过发送 retry 字段可以覆盖客户端的重连等待时间:
retry: 5000
注意:
retry字段单独占一行,前后不需要data:。服务端可以在任意时刻发送,客户端收到后立即生效。
4. 断点续传实现
SSE 协议原生支持断点续传,核心是 id 字段和 Last-Event-ID 请求头。
4.1 工作原理
- 服务端每条消息带一个唯一的、单调递增的
id - 客户端收到消息后,浏览器自动记录最后一条的
id - 连接断开后,浏览器重连时自动在请求头中携带
Last-Event-ID - 服务端读取这个头,从该 ID 的下一条开始推送
5. 与 WebSocket 的选型对比
5.1 对比表格
| 特性 | SSE | WebSocket |
|---|---|---|
| 通信方向 | 单向(服务器 → 客户端) | 双向(服务器 ↔ 客户端) |
| 协议 | 标准 HTTP (http:// / https://) |
独立协议 (ws:// / wss://) |
| 重连机制 | 浏览器内置自动重连 | 需要手动实现 |
| 断线续传 | 原生支持 (id + Last-Event-ID) |
需要自行设计 |
| 二进制数据 | 需 Base64 编码 | 原生支持 |
| 连接数限制 | HTTP/1.1 有限制,HTTP/2 可解决 | 无明显限制 |
| 实现复杂度 | 低 | 高 |
| 调试难度 | 低(HTTP 请求可见) | 中(需要专门工具) |
| 服务端压力 | 维护 HTTP 长连接 | 维护更复杂的协议状态 |
5.2 选型建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| AI 大模型流式输出 | SSE | 单向推送,实现简单,自动重连 |
| 实时监控大屏/行情看板 | SSE | 大量只读客户端,服务端负担轻 |
| 新消息提醒/订单状态通知 | SSE | 够用且简单,开发成本低 |
| 即时聊天/IM | WebSocket | 需要频繁双向交互 |
| 协同编辑(如 Google Docs) | WebSocket | 需要双向实时同步 |
| 在线游戏 | WebSocket | 极低延迟 + 双向二进制数据 |
| 需要兼容 IE | WebSocket 或 轮询 | IE 不支持 SSE |