一、实时通信概述

大家好,欢迎来到《Node.js与WebSocket实现实时通信》的第一章。

说实话,我刚开始接触Web开发那会儿,对「实时」这个词的理解特别肤浅。以为页面能自动刷新就是实时了。后来踩了不少坑,才真正搞明白——实时通信,说白了就是让数据在产生的那一刻,立刻到达对方手里。不是几秒后,不是下次请求时,就是现在。

什么是实时通信

咱们先把这个概念说清楚。

传统的HTTP通信,就像你给朋友寄信。你写好信(发送请求),朋友收到后回信(返回响应)。一来一回,中间有延迟。而且朋友不会主动给你写信,除非你先寄过去。

实时通信不一样。它更像打电话——两边随时可以说话,延迟几乎感觉不到。服务器也能主动给客户端发消息,不需要客户端先问。

我个人的理解是:实时通信 = 低延迟 + 双向主动推送。这两个条件缺一不可。

核心特征:

  • 延迟通常在毫秒级(几百毫秒以内)
  • 服务端可以主动推送数据
  • 连接建立后保持长连接状态

应用场景:你每天都在用

其实实时通信离我们很近。我随便举几个例子,你肯定都接触过。

在线聊天

微信、Slack、Discord,这些聊天工具的核心就是实时通信。你发一条消息,对方几乎同时收到。我记得有一次给朋友发「吃饭了吗」,他秒回「正在吃」——这种体验,靠HTTP轮询是做不到的。

协同编辑

Google Docs、飞书文档、Notion的多人协作功能。你在这边打字,同事那边实时看到变化。嗯,这里有个坑——协同编辑不只是传输文本,还要处理冲突。我曾经在一个项目里用WebSocket做协同编辑,结果两个人同时改同一段文字,数据乱成一锅粥。后来加了OT算法(操作转换)才搞定。

在线游戏

尤其是多人在线游戏,比如《王者荣耀》、《绝地求生》。每个玩家的位置、动作都要实时同步到其他玩家那里。延迟超过100ms,游戏体验就明显变差。我做过一个简单的联机贪吃蛇,用WebSocket同步蛇的位置,延迟控制在50ms以内,玩起来还算流畅。

股票行情

股票价格每秒都在变。你打开炒股软件,K线图实时跳动。这些数据就是通过实时通信推送到你屏幕上的。我有个朋友做量化交易,他说延迟多1毫秒,可能就少赚几万块——虽然夸张了点,但能看出实时性对金融场景有多重要。

场景 延迟要求 数据特点
在线聊天 < 1秒 小数据量,频率中等
协同编辑 < 200ms 小数据量,频率高
在线游戏 < 100ms 数据量中等,频率极高
股票行情 < 50ms 小数据量,频率极高

技术选型:怎么选?

实现实时通信,有好几种技术方案。我按出现时间从早到晚给你捋一遍。

轮询(Polling)

这是最原始的方式。客户端每隔几秒发一次HTTP请求,问服务器「有新数据吗?」。服务器每次都得响应,哪怕没新数据也得回个「没有」。

你想想看,这效率多低。大部分请求都是白问的。而且延迟取决于轮询间隔——设成1秒,延迟最多1秒;设成100ms,服务器压力又扛不住。

避坑:我曾经在一个监控面板项目里用了轮询,每2秒请求一次。用户量一上来,服务器CPU直接飙到90%。后来换成WebSocket,CPU降到20%不到。轮询真的只适合小规模、低频率的场景。

长轮询(Long Polling)

轮询的改进版。客户端发请求后,服务器不立即返回,而是把请求「挂」在那里。等有新数据了,再返回响应。客户端收到后,立刻再发一个新请求。

说白了,就是让服务器「等一会儿再回答」。这样减少了大量无效请求。但问题也很明显——每次请求都要建立HTTP连接,开销还是不小。而且如果服务器挂了,客户端可能一直等不到响应。

SSE(Server-Sent Events)

SSE是HTML5标准的一部分。它允许服务器通过一个HTTP连接,持续向客户端推送数据。客户端只需要用EventSource接口监听就行。

// 客户端代码
const eventSource = new EventSource('/stream');
eventSource.onmessage = (event) => {
  console.log('收到数据:', event.data);
};

SSE的优点是用起来简单,基于HTTP协议,兼容性好。但它是单向的——只能服务器推给客户端,客户端不能通过这个连接给服务器发数据。而且浏览器对SSE的连接数有限制(一般是6个)。

我的建议:如果你只需要服务器推送(比如股票行情、通知提醒),SSE是个不错的选择。但需要双向通信时,还是得用WebSocket。

WebSocket

终于说到主角了。WebSocket是HTML5提供的全双工通信协议。它通过一次HTTP握手,建立一条持久连接。之后客户端和服务器可以随时互相发数据,没有额外的HTTP开销。

WebSocket的延迟极低,通常在10ms以内。而且支持二进制数据,可以传图片、音频。我做过一个在线白板应用,用WebSocket同步画笔轨迹,延迟基本感觉不到。

技术 方向 延迟 开销 适用场景
轮询 单向(客户端主动) 高(取决于间隔) 高(大量无效请求) 低频率、小规模
长轮询 单向(客户端主动) 中等 中等 中等频率
SSE 单向(服务器推送) 服务器推送场景
WebSocket 双向 极低 极低 实时双向通信

怎么选?我的一点经验

说实话,没有银弹。选哪种技术,得看你的具体需求。

  • 简单通知、状态更新:SSE就够了,别杀鸡用牛刀。
  • 聊天、游戏、协同编辑:必须WebSocket,双向通信是刚需。
  • 临时方案、小项目:长轮询也能凑合用,但别指望它撑起大流量。
  • 老项目改造:如果浏览器兼容性要求高(比如要支持IE),轮询或长轮询可能是唯一选择。

我个人习惯是:新项目一律用WebSocket。原因很简单——它是最通用的方案,能覆盖绝大多数实时场景。而且Node.js对WebSocket的支持非常好,后面几章我会带你一步步实现。

好了,第一章就到这里。下一章我们开始动手,用Node.js搭建一个WebSocket服务。到时候你会看到,代码其实没你想的那么复杂。