在 WEB 应用中,服务器向客户端主动推送数据是实现实时更新的关键技术,主要有以下几种方式:
-
WebSocket
- 机制:基于 TCP 的全双工通信协议。建立连接后(通过 HTTP 升级握手),服务器和客户端可在同一连接上进行双向、低延迟的实时通信。服务器可随时主动向客户端推送数据。
- 特点:真正双向实时通信,延迟最低。
- 适用场景:在线聊天、实时游戏、协作编辑、金融行情推送等要求高实时性和双向交互的应用。
- 实现:前端使用
WebSocket API
(如new WebSocket(url)
),后端可使用各种支持 WebSocket 协议的库(如 Node.js 的ws
)。
-
Server-Sent Events (SSE)
- 机制:基于 HTTP 的单向通信协议。客户端通过
EventSource
API 发起一个到服务器的 HTTP 连接,服务器保持此连接打开并通过text/event-stream
格式持续发送数据流。服务器可主动推送数据,客户端只能接收。 - 特点:简单轻量(基于 HTTP),天然支持断线重连和事件类型,浏览器支持较好。
- 适用场景:新闻推送、实时公告、股票价格更新、状态监控等服务器向客户端单向推送数据的场景。
- 实现:前端使用
EventSource
(如new EventSource('/sse-endpoint')
),服务器需设置响应头Content-Type: text/event-stream
并持续写入符合格式的数据流。
- 机制:基于 HTTP 的单向通信协议。客户端通过
-
长轮询 (Long Polling)
- 机制:客户端发送一个 HTTP 请求到服务器。服务器不立即响应,而是挂起连接直到有数据可推或超时。当有数据时,服务器立即响应;若超时无数据,服务器返回一个空响应,客户端随后立即发起一个新的请求。
- 特点:相较传统轮询(间隔固定时间请求),减少了无效请求次数和延迟。
- 适用场景:兼容性要求高(老浏览器)、需要实现简单推送且实时性要求适中的场景。
- 实现:前端使用常规的
XHR
或Fetch API
发起请求,服务器端需要维护挂起的请求并在有数据时响应。
-
HTTP 流 (HTTP Streaming)
- 机制:客户端发起一个 HTTP 请求,服务器保持连接打开并持续通过分块传输编码(
Transfer-Encoding: chunked
)或其他流式技术向客户端发送数据片段。 - 特点:保持单一 HTTP 连接,服务器可连续推送多个数据块。
- 适用场景:需要服务器持续发送多个数据更新,替代多次轮询或长轮询。
- 实现:服务器设置
Transfer-Encoding: chunked
并持续写入响应体,客户端通过监听XHR
的onprogress
或Fetch API
的ReadableStream
来处理接收到的片段。
- 机制:客户端发起一个 HTTP 请求,服务器保持连接打开并持续通过分块传输编码(
下表总结了主要推送方式的核心区别:
方式 | 协议基础 | 通信方向 | 实时性 | 复杂度 | 典型场景 |
---|---|---|---|---|---|
WebSocket | TCP (独立协议) | 全双工 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 即时通讯、实时游戏、高频交易 |
SSE | HTTP | 单向(服务端→客户端) | ⭐⭐⭐ | ⭐⭐ | 新闻推送、股票报价、实时监控 |
长轮询 | HTTP | 模拟单向 | ⭐⭐ | ⭐⭐ | 兼容性要求高的旧系统 |
HTTP 流 | HTTP | 单向 | ⭐⭐ | ⭐⭐ | 持续数据流(如日志流) |
📌 淘汰或小众方案:历史上还出现过
隐藏iframe
、<script>
标签流等模拟推送的方法,但因其缺点明显(如占用连接资源、安全性问题、兼容性差),在现代 Web 开发中基本已被淘汰,不再推荐使用。
选择建议:
- 需要双向实时通信 → WebSocket。
- 只需服务器单向推送且追求简单轻量 → SSE (优于长轮询/HTTP流)。
- 兼容性要求极高(需支持非常老旧浏览器)且仅需单向推送 → 可考虑长轮询。
实际应用中,服务端实现需注意连接管理、状态维护、性能优化和扩展性等问题。