为什么 WebSockets 对大多数实时应用来说是大材小用

发布: (2026年2月5日 GMT+8 08:20)
7 min read
原文: Dev.to

Source: Dev.to

WebSockets vs SSE

在构建实时功能时,大家往往会直接使用 WebSocket。实际上,大多数应用只需要单向更新——而 服务器发送事件(SSE) 能以更好、更简洁、更低成本的方式实现这一需求。

下面我们来拆解一下 WebSocket 在什么情况下真正有意义——以及在什么情况下并不适用。

WebSocket 默认问题

“实时”已成为“使用 WebSockets”的代名词。
但这种假设跳过了一个关键问题:

到底是谁在说话?

在大多数真实世界的应用中,答案很简单:

  • 服务器 产生更新
  • 客户端 监听并渲染

这不是对话,而是流。

然而团队仍然要付出 WebSocket 的代价:

  • 更多代码
  • 更多状态
  • 更难扩展
  • 额外的调试痛苦

通常是为了那些从不回传数据的功能。

大多数实时功能的真实样子

这些本质上是单向的

  • 仪表盘(指标、分析、监控)
  • 通知与警报
  • 活动流
  • 股票或加密货币行情
  • CI/CD 构建状态
  • 日志流
  • AI 响应流
  • 系统健康更新

在所有这些场景中,数据流向为 server → client
客户端输入(如果有)通过普通的 HTTP 请求完成。这正是 SSE 发光发热的地方。

当 WebSocket 真正重要时

WebSocket 是在以下情况下的正确工具:

  • 持续的双向通信
  • 客户端驱动的状态变化
  • 超低延迟
  • 二进制数据传输

示例

  • 多人游戏
  • 协同编辑器
  • 实时交易终端
  • 语音/视频信令

这个类别确实存在——只不过比大多数团队想象的要小得多。

什么是服务器发送事件 (SSE)?

SSE 是一种长连接的 HTTP,服务器在事件发生时实时推送更新。无需协议升级、无需自定义帧、也不需要心跳技巧——仅仅是 HTTP。

客户端(浏览器)

const source = new EventSource('/events');

source.onmessage = (e) => {
  console.log(JSON.parse(e.data));
};

服务器(Node.js)

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

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

  req.on('close', () => clearInterval(interval));
});

这就是一个可工作的实时流——无需任何库。

为什么 SSE 是更好的默认选择

1. 它只是 HTTP

SSE 运行在标准 HTTP(80/443)上:

  • 能在代理后工作
  • 能与 CDN 配合使用
  • 能在企业网络中使用
  • 只要 HTTP 能通,就能通

在受限环境下,WebSocket 往往会悄然失效。

2. 自动重连已内置

如果连接中断:

  • 浏览器会自动重新连接
  • 并带有退避策略
  • 完全不需要你写任何代码

使用 WebSocket 时,重连逻辑 全是你的事

3. 调试非常简单

想要检查实时数据?

curl -N https://example.com/events

立刻可见。无需特殊工具。

4. 性能几乎相同

在真实系统中:

  • 网络延迟占主导
  • 数据库延迟占主导
  • 渲染时间占主导

协议之间的差异通常只有 毫秒级——对仪表盘、信息流和通知的用户来说几乎不可感知。

5. HTTP/2 消除了旧限制

过去的担忧:“浏览器限制连接数”。
使用 HTTP/2:

  • 单一 TCP 连接
  • 多路复用多个流
  • 实际上没有连接上限

现代浏览器和服务器已经支持这一点。

SSE 的实际应用

AI 流式响应

用户通过 POST 发送提示。服务器流式返回令牌。客户端逐步渲染。不需要双向通道。

可观测性与监控

指标和日志由服务器生成。客户端仅进行监听。SSE 使系统保持简单且可扩展。

功能标志和配置更新

客户端监听变化。它们不进行协商。是 SSE 的理想场景。

当 SSE 不适用时

避免在需要以下情况时使用 SSE:

  • 二进制流传输
  • 持续的客户端输入
  • 子 10 毫秒 延迟保证
  • 点对点协商

这时 WebSockets(或 WebRTC)才发挥作用。

常见 SSE 陷阱(已解决)

  • 缓冲响应 → 禁用代理缓冲
  • 空闲超时 → 发送轻量心跳
  • 水平扩展 → 使用 Redis/Kafka 作为后端总线
  • 身份验证 → 使用 cookie 或短期令牌

这些都是已解决的问题——不是阻碍。

更好的思维模型

Instead of asking:

“我们需要实时吗?”

Ask:

“谁在说话,谁在倾听?”

If the server does most of the talking, SSE should be your first choice. WebSockets should be intentional, not automatic.

底线

WebSockets 功能强大——但往往并非必需。对于大多数实时功能,服务器发送事件(Server‑Sent Events)

  • 更简单
  • 更易调试
  • 更易扩展
  • 更易维护
  • 在生产环境中更可靠

枯燥的技术在生产中更受青睐。对于服务器到客户端的流式传输,SSE 是那种枯燥且正确的选择


讨论
你在应用中如何处理实时功能?是否曾在本可以使用 SSE 的情况下使用了 WebSockets,或反之亦然?欢迎分享你的真实经验。

Back to Blog

相关文章

阅读更多 »

HTTP 推送机制

传统的 HTTP Pull 模型 默认情况下,Web 通信遵循 HTTP Pull 模型: - client 发送请求 - server 处理请求 - server …