单向服务端推送选SSE,双向实时交互必须用WebSocket;SSE基于HTTP、自动重连、断点续传,WebSocket需手动处理握手、心跳与重连。

只用服务端推数据,SSE 就够了;需要客户端随时发消息回来,才必须上 WebSocket。
EventSource 和 WebSocket API 的调用差异
浏览器端建立连接的方式完全不同,不能混用或替换:
-
EventSource是原生全局对象,构造时传一个普通 HTTP URL:new EventSource("/events"),它自动处理 GET 请求、重连、Last-Event-ID头部携带 -
WebSocket构造时必须用ws://或wss://协议前缀:new WebSocket("wss://api.example.com/ws"),且需手动监听open、message、error、close四类事件 -
EventSource不支持发送数据,没有send()方法;WebSocket必须调用send()才能发消息,否则连接只是“挂起” - 两者都受同源策略限制,但
EventSource可通过服务端返回Access-Control-Allow-Origin支持跨域,WebSocket跨域依赖服务器在握手阶段校验Origin头
text/event-stream 和 WebSocket 握手的协议成本
SSE 本质就是一次 HTTP GET,而 WebSocket 需要一次 HTTP Upgrade 升级协商:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- SSE 响应头只需三行:
Content-Type: text/event-stream、Cache-Control: no-cache、Connection: keep-alive;任何反向代理(Nginx、ALB、Cloudflare)默认透传 - WebSocket 初始请求带
Upgrade: websocket和Connection: Upgrade,很多企业网关、WAF、老旧 CDN 会直接拒绝或超时中断,调试时常见502 Bad Gateway或连接卡在pending - HTTP/2 下 SSE 天然复用连接,无额外开销;WebSocket 在 HTTP/2 中实际走的是
h2c伪协议,部分负载均衡器不支持,仍得降级到 HTTP/1.1 - 服务端实现上,SSE 只需普通路由 handler 持有 response 对象写入流;WebSocket 需维护 socket 生命周期、心跳 ping/pong、连接池管理
SSE 的 id: 和 Last-Event-ID 是怎么续传的
这是 SSE 真正被低估的机制——不是“可选功能”,而是浏览器强制行为:
- 只要服务端响应中某次写了
id: 123\n,后续所有推送都会带上该 ID;断连重试时,浏览器自动在新请求头里加Last-Event-ID: 123 - 服务端收到该 header 后,应从 ID=124 开始继续推送,跳过已送达事件;若忽略该 header,用户会重复收到 123 及之后的消息
- 注意:ID 必须是字符串,
id: 123和id: "123"效果一致;但id:(空值)会导致浏览器清空本地 ID 缓存,下次重连不带该 header - WebSocket 没有等价机制,要实现类似效果,得自己设计消息序号、ACK 确认、服务端消息回溯存储,复杂度指数上升
自动重连的 timeout 行为差异
看似都是“断了再连”,但触发逻辑和可控性天差地别:
-
EventSource默认重试间隔约 3 秒,可通过服务端retry: 5000\n指令修改(单位毫秒),浏览器严格遵守;客户端无法干预或取消 -
WebSocket断开后完全静默,不重连;必须手写重连逻辑,包括退避策略(如指数增长)、最大重试次数、是否清空待发队列等 - 当网络抖动导致短暂失联,SSE 用户几乎无感;WebSocket 用户常看到“连接已断开”提示,除非团队专门封装了健壮的重连 SDK
- 服务端主动关闭 SSE 连接,推荐返回 HTTP 204(No Content)并结束流;若直接 close response,浏览器可能误判为异常并立即重试
真正容易被忽略的点在于:SSE 的“简单”不是功能少,而是把高频刚需(重连、断点、HTTP 兼容)交给了浏览器实现;而 WebSocket 把这些全留给了开发者。选错协议,后期补救的成本远高于初期多花一小时画清数据流向箭头。

















