实时通信能力已经成为现代 Web 应用的基础设施。无论是聊天消息、协同编辑、股票行情还是任务进度推送,开发者都需要在浏览器与服务端之间建立一条“持续在线”的数据通道。在众多技术方案中,WebSocket 和 Server-Sent Events(SSE)是最常被拿来比较的两种。它们都基于 HTTP 生态,却走向了不同的设计方向。理解它们的差异与适用场景,比单纯记住“谁更好”更重要。
为什么需要实时通信
传统的 HTTP 请求-响应模型是“拉”模型:客户端不问,服务端不答。要实现实时更新,早期只能靠轮询或长轮询。轮询会产生大量无效请求,长轮询虽然减少了空请求,但每次消息推送后连接都会断开,服务端需要维护复杂的挂起逻辑。WebSocket 和 SSE 都是对“服务端主动推送”这一需求的直接回应,只是它们选择了不同的协议路径。
WebSocket:全双工的双向通道
WebSocket 是一种独立的网络协议,通过 HTTP 的 Upgrade 机制完成握手,之后便脱离 HTTP 语义,在一条 TCP 连接上进行全双工通信。
它的核心特点包括:
- 双向通信:客户端和服务端可以随时向对方发送消息,没有“谁先谁后”的限制。
- 低开销:握手完成后,数据帧头部很小,没有 HTTP 头部的重复开销。
- 二进制支持:除了文本,还可以直接传输 ArrayBuffer 等二进制数据。
- 独立协议:使用
ws://和wss://协议标识,需要服务端和客户端都支持 WebSocket。
WebSocket 的典型应用场景是聊天室、多人游戏、协同编辑、实时交易系统等需要频繁双向交互的场景。例如,在一个在线协作文档中,每个用户的每一次光标移动和文字输入都需要即时同步给其他人,这种高频双向通信正是 WebSocket 的强项。
但 WebSocket 也带来了额外的复杂度:服务端需要维护连接状态、处理心跳与重连、考虑横向扩展时的连接路由问题。如果只是单向推送,这些成本可能并不划算。
SSE:轻量的服务端推送
SSE 则走了另一条路。它完全基于 HTTP,客户端通过一个普通的 GET 请求建立连接,服务端以 text/event-stream 格式持续返回数据。浏览器内置了 EventSource API,自动处理连接、重连和事件解析。
SSE 的特点包括:
- 单向推送:只有服务端能向客户端发送消息,客户端无法通过同一连接回传数据。
- 基于 HTTP:无需协议升级,天然兼容现有 HTTP 基础设施,包括代理、负载均衡和认证。
- 自动重连:浏览器会自动处理断线重连,并支持
Last-Event-ID机制,服务端可以据此补发丢失的消息。 - 文本协议:只支持 UTF-8 文本,二进制数据需要额外编码。
SSE 适合的场景是“服务端单向通知客户端”:新闻推送、股票价格更新、任务进度条、日志流、社交媒体时间线等。例如,一个后台任务系统需要把执行日志实时推送给前端,使用 SSE 只需要一个 HTTP 接口,代码量远小于 WebSocket。
SSE 的局限也很明显:客户端无法通过同一连接发送数据。如果需要客户端回传信息,必须另开一个 HTTP 请求,这在双向交互频繁的场景中会显得笨拙。
关键维度对比
| 维度 | WebSocket | SSE |
|---|---|---|
| 通信方向 | 全双工 | 服务端到客户端单向 |
| 协议 | 独立协议,需 Upgrade | 纯 HTTP |
| 数据格式 | 文本 + 二进制 | 仅文本 |
| 自动重连 | 需自行实现 | 浏览器内置 |
| 连接数限制 | 每域名约 200 个(HTTP/1.1) | 每域名约 6 个(HTTP/1.1) |
| 代理兼容性 | 部分代理可能阻断 | 兼容性极好 |
| 实现复杂度 | 较高 | 较低 |
连接数限制值得特别说明。在 HTTP/1.1 下,浏览器对同一域名的并发连接数有限制,SSE 会占用其中一个。如果页面同时打开多个 SSE 连接,可能很快耗尽配额。而 WebSocket 不受此限制。不过,在 HTTP/2 下,多路复用让这个问题基本消失,SSE 的连接数限制不再成为瓶颈。
落地实践中的选择建议
在实际项目中,选择哪种方案取决于业务需求,而不是技术偏好。
优先选择 WebSocket 的情况:
- 需要客户端和服务端频繁双向通信,如聊天、游戏、协同编辑。
- 需要传输二进制数据,如文件流、音视频帧。
- 对延迟极度敏感,且需要客户端主动发起消息。
优先选择 SSE 的情况:
- 只需要服务端单向推送,如通知、行情、进度更新。
- 希望复用现有 HTTP 认证、代理和监控体系。
- 团队希望降低服务端连接管理的复杂度。
- 需要浏览器自动重连和断点续传能力。
混合方案: 在一些复杂场景中,可以同时使用两者。例如,用 SSE 接收服务端推送的实时数据,用普通 HTTP 请求发送客户端操作。这样既享受了 SSE 的简单和自动重连,又避免了 WebSocket 的全双工复杂度。另一种常见模式是:用 WebSocket 做双向控制通道,用 SSE 做大规模数据分发通道。
服务端实现要点
无论选择哪种方案,服务端都需要注意几个共性问题。
连接管理: 需要维护活跃连接列表,在连接断开时及时清理,避免内存泄漏。对于 WebSocket,还需要实现心跳机制(Ping/Pong)来检测死连接。
横向扩展: 单机连接数有上限,多实例部署时需要引入消息中间件(如 Redis Pub/Sub、NATS)来广播消息,确保所有实例上的连接都能收到对应事件。
背压处理: 当客户端消费速度慢于服务端生产速度时,需要有缓冲或丢弃策略,避免内存无限增长。
安全: WebSocket 和 SSE 都基于 HTTP 握手,可以复用 Cookie、Token 等认证方式。但需要注意跨域配置和 CSRF 防护。
小结
WebSocket 和 SSE 不是竞争关系,而是针对不同需求的两种工具。WebSocket 提供了最完整的实时通信能力,但代价是更高的实现复杂度和运维成本。SSE 以极简的 HTTP 语义实现了服务端推送,在单向场景中几乎是零成本的选择。
一个实用的决策原则是:先问通信方向,再问数据格式,最后问基础设施。 如果只需要服务端推、客户端收,SSE 通常是更优雅的方案;如果需要真正的双向对话,WebSocket 才是正确答案。理解这一点,就能在具体项目中做出更务实的架构选择。
未经允许不得转载:任鹏个人博客 » WebSocket 与 SSE:实时通信方案的对比与落地


朋友圈点赞图在线生成源码