← 返回题目列表

Server-Sent Events 是什么?它和 WebSocket、普通轮询有什么区别?

中等 第 27 / 32 题 更新于 2026/08/02
HTTPSSE实时通信

简化版

Server-Sent Events,简称 SSE,是基于 HTTP 的服务端单向推送机制。

客户端通过 EventSource 建立一个长连接,服务端用 text/event-stream 持续向客户端发送事件流。它适合通知、进度、消息流、监控面板等“服务端不断推给客户端”的场景。

和 WebSocket 相比,SSE 是单向推送、基于 HTTP、实现简单、天然支持断线重连;WebSocket 是全双工通信,更适合双向实时交互。

详细版

SSE 响应头通常是:

HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

事件格式类似:

event: message
id: 101
data: hello

浏览器端:

const es = new EventSource("/events");
es.onmessage = (event) => console.log(event.data);

SSE 只能服务端推客户端,客户端要发消息仍然走普通 HTTP 请求。

它比轮询节省请求开销,比 WebSocket 简单,但不适合强双向互动和二进制传输。

完整版教学

1. 先给出 SSE 的定位

SSE 是浏览器和服务端之间的一条 HTTP 长连接。

连接建立后,服务端可以不断往客户端写事件。

客户端只负责接收。

这和“客户端不断问服务端有没有新数据”的轮询不同。

SSE 的关键词是:HTTP、长连接、服务端单向推送、文本事件流。

2. SSE 的响应格式

服务端响应头通常包含:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

响应体是一段持续输出的文本流。

每个事件由若干字段组成,并用空行分隔。

id: 1
event: progress
data: {"percent":30}

id: 2
event: progress
data: {"percent":60}

客户端收到空行后认为一个事件结束。

3. 浏览器如何使用

浏览器原生提供 EventSource

const source = new EventSource("/api/events");

source.addEventListener("progress", (event) => {
  console.log(event.data);
});

source.onerror = () => {
  console.log("connection error");
};

如果连接断开,浏览器会自动尝试重连。

服务端可以通过 id 配合 Last-Event-ID 帮助客户端从断点继续。

4. 和轮询、长轮询、WebSocket 对比

方案通信方向协议基础优点适合场景
短轮询客户端反复请求HTTP简单低频状态刷新
长轮询请求挂起等待结果HTTP兼容性好中低频通知
SSE服务端持续推送HTTP简单、自动重连消息流、进度
WebSocket双向通信独立升级协议全双工聊天、游戏、协作

SSE 不需要协议升级,部署上通常比 WebSocket 更接近普通 HTTP。

5. SSE 的限制

SSE 不是万能实时方案。

它有一些限制:

  • 主要传文本,不适合直接传二进制。
  • 通信方向是服务端到客户端。
  • 部分代理可能缓冲响应,导致事件不能及时到达。
  • 浏览器对同域连接数有限制。
  • 长连接会占用服务端连接资源。

如果业务需要客户端高频发送消息,WebSocket 更合适。

6. 工程实践注意点

实现 SSE 时要注意:

  • 关闭代理缓冲,例如 Nginx 的 buffering。
  • 定期发送心跳,避免连接被中间设备断开。
  • 设置合理的重试间隔。
  • 每个事件带 id,便于断线恢复。
  • 服务端使用异步 I/O 或事件驱动模型承载大量连接。
  • 不要让响应被普通缓存缓存。

一个心跳事件可以很简单:

: ping

冒号开头是注释行,客户端可忽略,但能保持连接活跃。

7. 常见误区与追问

  • 误区:SSE 和 WebSocket 一样是双向通信。 SSE 主要是服务端到客户端的单向推送。
  • 误区:SSE 只是普通轮询。 SSE 是一次长连接持续接收事件,不是反复建立请求。
  • 误区:SSE 不需要考虑连接资源。 长连接会占用连接和内存,需要服务端模型支持。
  • 追问:SSE 为什么适合进度条? 服务端可以持续推送当前进度,客户端实时更新。
  • 追问:断线后怎么恢复? 使用事件 id 和 Last-Event-ID,服务端按需补发。
  • 追问:为什么代理缓冲会影响 SSE? 代理如果攒够数据再转发,客户端就无法实时收到事件。

8. 加强记忆

SSE 记成“HTTP 上的服务端喇叭”:服务端一直说,客户端一直听。

如果题目问实时通信选择,先判断单向还是双向,再决定 SSE 或 WebSocket。