WebSocket 和 SSE 怎么选?实时通信入门与避坑

前言

做实时功能时,很多团队都会遇到同一个问题:消息推送到底用 WebSocket 还是 SSE?

如果只是"能跑起来",两者都能做;但到了线上,连接数、稳定性、网关兼容、开发复杂度都会影响结果。

这篇文章用工程视角讲清三件事:

  1. 两者的本质区别;
  2. 典型业务场景该怎么选;
  3. 上线前最容易踩的坑有哪些。

一、先给结论:一句话理解两者

  • WebSocket:全双工,客户端和服务端都可以主动发消息,适合高频双向交互。
  • SSE(Server-Sent Events):服务端单向推送到客户端,基于 HTTP,适合"服务端通知客户端"类场景。

如果你现在只记一条:
只需要服务端推送,用 SSE 先赢一半复杂度;双向实时互动,直接 WebSocket。


二、核心差异对比(工程最关心的维度)

维度 WebSocket SSE
通信方向 双向 单向(服务端 -> 客户端)
协议基础 ws:// / wss:// HTTP(text/event-stream)
连接维护 需处理心跳、断线重连 浏览器原生支持自动重连(可配)
数据格式 文本/二进制都可 主要是文本流
适用场景 聊天、协同编辑、游戏、交易终端 通知流、日志流、任务进度、AI输出流式展示
实现复杂度 较高 较低

三、典型场景怎么选

场景 1:AI 对话流式输出

用户发请求后,前端只需要不断接收模型输出。

这类是标准"服务端持续推送",SSE 更轻量,接入成本低。

场景 2:IM 聊天室

客户端要发消息、撤回、输入状态同步,服务端也要广播。

这是典型双向高频,WebSocket 更合适。

场景 3:运维看板/实时监控

浏览器端只看状态更新,不太需要主动发。

优先 SSE;如果后续要双向控制,再评估迁移 WebSocket。


四、最小代码示例

4.1 SSE:Node.js(Express)服务端

js 复制代码
import express from "express";

const app = express();

app.get("/events", (req, res) => {
  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Connection", "keep-alive");

  const timer = setInterval(() => {
    res.write(`data: ${JSON.stringify({ ts: Date.now() })}\n\n`);
  }, 1000);

  req.on("close", () => clearInterval(timer));
});

app.listen(3000);

4.2 前端订阅 SSE

js 复制代码
const es = new EventSource("/events");
es.onmessage = (e) => {
  const payload = JSON.parse(e.data);
  console.log("收到推送", payload);
};

这套代码就能跑出"服务端持续推送,前端实时显示"的最小闭环。


五、上线最常见的 4 个坑

5.1 反向代理超时

Nginx/网关如果默认超时较短,会导致长连接被频繁断开。

需要针对长连接路由单独配置超时与缓冲策略。

5.2 忘记做重连与幂等消费

不管 WebSocket 还是 SSE,真实网络都会抖动。

客户端要有重连逻辑,服务端要避免消息重复处理。

5.3 心跳机制缺失(WebSocket)

没有心跳时,连接可能"看起来在线,实际上不可用"。

建议服务端和客户端都实现 ping/pong 或应用层心跳。

5.4 把实时链路当普通 HTTP 接口压测

连接数、广播风暴、消息堆积和普通 QPS 不是一套指标。

实时系统要看:在线连接数、消息延迟、断线率、重连成功率。


六、实战建议:从"够用"开始,不要一步到位过度设计

可以按下面顺序决策:

  1. 先判断是否需要双向;不需要就优先 SSE;
  2. 评估连接规模与消息频率,确认网关和实例承载;
  3. 加入可观测性(连接数、延迟、断线率)再扩大流量;
  4. 当业务从"通知"演进为"交互",再升级到 WebSocket。

这比一开始就上复杂通信栈更稳,也更省研发成本。


总结

WebSocket 和 SSE 没有绝对优劣,关键看你是"实时通知"还是"实时交互"。

工程上最实用的原则是:能用 SSE 先用 SSE,必须双向再上 WebSocket。

你们现在线上的实时需求主要是通知流,还是双向交互?评论区说下场景,一起交流学习~~~

相关推荐
我不会插花弄玉6 小时前
6.传输层协议UDP【由浅入深-网络】
网络·网络协议·udp
火云代理7 小时前
更换网络后为什么会退出登录?分清 IP、Cookie 与会话的关系
服务器·网络·网络协议·tcp/ip·php·ip
xbzb9 小时前
容器 IP 每次重建都变?docker network 五种模式与自定义网桥固定地址
网络·docker·容器·ip·network·固定
火云代理10 小时前
同一个网站,有的网络能打开、有的打不开?认识 IPv4 与 IPv6 的访问差异
服务器·网络·网络协议·tcp/ip·测试工具·php·状态模式
坤坤子吖11 小时前
Linux网络编程:TCP 粘包与半包问题,如何正确处理 TCP 流式数据?
linux·服务器·网络·笔记·网络协议·学习
火云代理14 小时前
Python 使用代理 IP 前,先弄清 Requests 的配置来源与验证方法
网络·python·网络协议·tcp/ip·ip
如夏倾城14 小时前
QUIC——HTTP/3 的唯一底层传输协议 及 0-RTT恢复
网络·网络协议·tcp/ip·安全·http
科研邪修法15 小时前
培训PDF保护配置:把需求转换成可验收权限
linux·服务器·网络
略懂而已2 天前
安装SSL后网站速度变慢?
网络·网络协议·ssl