EventSource专用于服务端单向推送,自动重连、零握手、HTTP原生兼容;WebSocket需手动处理双向通信、心跳及重连,仅在需客户端高频发消息或传二进制数据时不可替代。

只用服务端推数据,别碰WebSocket
如果你的需求只是让后端把日志、AI输出、行情、通知这类内容“流式吐给前端”,WebSocket 是过度设计。它强制你处理握手、心跳、重连、帧解析,而这些在 EventSource 里全是浏览器自动干的。很多团队上线后才发现:90% 的连接问题来自代理超时、ALB 升级头被丢弃、Nginx 默认关长连接——而 SSE 走的是标准 HTTP,所有中间件照单全收。
EventSource 自动重连不是“可选项”,是默认行为
浏览器发起 new EventSource("/events") 后,只要连接断开(网络抖动、服务重启、负载均衡切换),它会在约 3 秒后自动重试,无需任何代码。这个重连间隔还能用 retry: 字段控制:
data: {"msg": "hello"}\nid: 123\nretry: 10000\n\n
下一次重连时,浏览器会带上 Last-Event-ID: 123 请求头,服务端据此续推,避免漏消息。而 WebSocket 的重连必须自己写逻辑,退避策略、连接状态管理、重复订阅防重,每个项目都在重复造轮子。
text/event-stream 格式简单但有硬约束
SSE 不是“随便写点 JSON 往 response.write 里塞”,必须遵守几条铁律:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 响应头必须包含
Content-Type: text/event-stream和Cache-Control: no-cache - 每条消息以
data:开头,结尾用两个换行符\n\n分隔 - 不能混用
res.end()或提前关闭连接;客户端断开时监听req.on("close")清理定时器 - 若要支持跨域,必须显式设置
Access-Control-Allow-Origin,EventSource不发预检请求,但同源策略照常生效
违反任意一条,EventSource 就静默失败,不会报错,只会卡住或反复重连——这是最常踩的坑。
WebSocket 真正不可替代的只有两个场景
当你需要以下任一能力时,WebSocket 才是唯一解:
- 客户端要高频、低延迟地向服务端发消息(比如聊天输入、游戏操作、协同编辑光标移动)
- 必须传二进制数据(如音视频帧、protobuf 序列化对象、Canvas 导出图片流)
注意:如果只是偶尔发个确认、撤回、已读标记,完全可以用 fetch 或 axios 配合 SSE 推送状态变更——混合使用才是常态,不是非此即彼。强行把单向推送塞进 WebSocket,等于给自行车装涡轮增压,徒增复杂度和故障面。










