2026 年 Node.js SaaS 应用最佳托管 WebSocket 与实时消息平台
实时产品功能看似简单,但要做好,成本高得容易被低估。第一个原型通常很容易:
browser ── WebSocket ──> Node.js server
然后生产环境的需求就来了。用户会打开多个标签页。移动客户端会在 Wi-Fi 和蜂窝网络之间切换。连接会断开又重连。一个客户可能有数千名员工同时订阅同一个实时仪表盘。在线状态必须区分“浏览器被关闭”和“网络暂时丢失”。聊天需要历史记录。部署可能要在数万客户端在线时重启每个 Node.js 进程。
到这一步,问题就不再是“我怎么打开一个 WebSocket?”,而变成了:谁来负责连接状态、扇出、消息顺序、在线状态、授权、重连、恢复、历史记录、背压、全局路由和容量?
托管实时平台可以移除很大一部分运营负担。对于 2026 年的 Node.js SaaS 团队,有五个强选项:
- Ably
- Pusher Channels
- PubNub
- Azure Web PubSub
- Amazon API Gateway WebSocket APIs
它们在技术上有所重叠,但定价模型差异很大。实时流量由两个普通 HTTP API 不太会直接暴露的维度驱动:连接时长和扇出。一次向 10,000 个订阅者发布,不是“一个工作单元”;它可能产生超过 10,000 次计费投递。
快速推荐
- 选择 Ably:当实时能力是严肃的产品能力,并且你需要全球托管的 pub/sub、在线状态、历史记录、连接恢复、强可用性目标,以及从 $29/月生产套餐到企业规模的清晰路径。
- 选择 Pusher Channels:当开发者简单性优先,基于并发连接数加每日消息量的固定套餐更容易预算。
- 选择 PubNub:当产品天然可以按月度活跃用户计量。PubNub 的核心平台定价围绕 MAU,在聊天、在线状态、持久化、审核和全球消息方面尤其强。
- 选择 Azure Web PubSub:当 Azure 已经是你的应用平台。它提供按单位计量的托管 WebSocket/pub-sub 容量,在付费层每个单位最多支持 1,000 个并发客户端连接。
- 选择 Amazon API Gateway WebSocket APIs:当 AWS 已经是控制平面,并且你更喜欢底层基础设施构建块。
实时消息不等同于响应流式传输
Node.js SaaS 团队越来越多地用流式输出 AI 生成响应。这并不自动需要 WebSocket。对于单向渐进输出,更简单的技术可能更好:HTTP 响应流、Server-Sent Events 或分块 HTTP。
当你需要服务端到客户端推送、客户端到服务端事件、长连接双向会话、每个事件多个订阅者、在线状态、房间/频道、协同更新、重连恢复或设备同步时,才使用托管 WebSocket/pub-sub。
一个 LLM 答案从一次 API 请求流式输出给一个用户,可能不需要全球实时平台。一个有几十个客服和客户的实时支持房间,可能就需要。
生产架构
一个稳健的 SaaS 设计会把三类职责分开:
- 持久业务状态
- 授权/控制平面
- 实时投影/投递
PostgreSQL ──> source of truth
│
v
Node.js API ──> authenticate user ──> resolve tenant ──> issue realtime
capability/token ──> commit business transaction ──> publish event
│
v
Managed realtime platform ──> fanout, presence, reconnect, history/recovery
│
v
browser / mobile clients
不要只把 WebSocket 层当作重要状态的唯一副本。一个实时 invoice.paid 事件应该更新或使 UI 失效。权威发票仍然在事务数据库中。
2026 年对比
| 平台 | 最适合 | 入门价格 | 计费驱动 | Node.js 适配 | 企业级信号 |
|---|---|---|---|---|---|
| Ably | 严肃的托管实时 / 全球扇出 | 免费;Standard $29/月 + 用量;Pro $399/月 + 用量 | 消息 + 连接/频道分钟数,或 MAU | 官方 Node.js/JS SDK | 99.999% 企业级 SLA、CNAME、SSO/SCIM |
| Pusher Channels | 快速、简单集成 | 免费;Startup $49/月;Pro $99/月 | 每日消息 + 并发连接 | 官方 Node.js 服务端库 | 自定义 Enterprise |
| PubNub | 采用 MAU 经济性的全球消息 | 免费;Starter $98/月,含 1,000 MAU | MAU | JS/TS SDK;SDK 12 要求 Node.js 22+ | 最高 99.999% SLA |
| Azure Web PubSub | Azure 原生实时 | 免费 + Standard/Premium 按区域定价 | 单位 + 出站消息量 | Azure SDK / 对 Node.js 友好 | Premium 可用区、自动缩放、异地复制 |
| API Gateway WebSocket | AWS 原生构建块 | 按使用付费 | 消息 + 连接分钟数 | Lambda/AWS SDK / 对 Node.js 友好 | IAM/Lambda 授权、SAM/CDK/CloudFormation |
1. Ably:最佳托管实时默认选择
当实时能力是重要产品能力,而不是小的 UI 增强时,Ably 是最强的通用默认选择。它的平台涵盖 pub/sub 频道、实时连接、在线状态、历史记录、连接恢复、全球扇出、Chat、共享状态产品、集成,以及企业级路由/可观测性。
当前套餐价格:
- 免费版:$0,200 个并发连接,500 条消息/秒,600 万条消息/月。
- Standard:$29/月 + 用量,10,000 个并发连接,2,500 条消息/秒。
- Pro:$399/月 + 用量,50,000 个并发连接,10,000 条消息/秒。
- Enterprise:定制,含无限容量、24/7 关键任务支持和 99.999% 可用性 SLA。
Ably 公布的按分钟定价为:每百万条消息 $2.50,每百万连接分钟 $1,每百万活跃频道分钟 $1。它还提供 MAU 模式,标价为每个 MAU $0.05,量大可折扣。
扇出是最关键的成本杠杆。一条发布投递给十个订阅者,会产生一次入站发布加多次订阅者投递。消息大小也很重要:Ably 按 5 KiB 块计量消息,所以大型状态快照会成倍增加账单。
更好的事件是小而面向持久状态的:
{ "type": "project.updated", "projectId": "prj_17", "version": 81 }
浏览器可以在必要时通过普通 API 获取完整状态。Node.js 集成很简单:
import * as Ably from "ably";
const ably = new Ably.Rest({ key: process.env.ABLY_API_KEY! });
await ably.channels
.get("tenant:org_42:project:prj_17")
.publish("project.updated", { projectId: "prj_17", version: 81 });
不要将根 API key 暴露给浏览器。客户端应当从 Node.js 后端获取短期、限制能力的凭据。
2. Pusher Channels:最适合快速、简单集成
Pusher Channels 拥有非常清晰的开发者模型:服务端触发事件,频道接收事件,订阅客户端收到更新。它支持公共频道、私有频道、私有加密频道、在线状态频道、缓存频道、webhooks、指标以及服务端/客户端库。
当前价格包括:
- Sandbox:免费,200,000 条消息/天,100 个并发连接。
- Startup:$49/月,100 万条消息/天,500 个并发连接。
- Pro:$99/月,400 万条消息/天,2,000 个并发连接。
- Business:$299/月,1000 万条消息/天,5,000 个并发连接。
- Premium:$499/月,2000 万条消息/天,10,000 个并发连接。
- Growth:$699/月,4000 万条消息/天,15,000 个并发连接。
Pusher 同时计入站发布和投递。一条发布投递给 50 个订阅者,大约是 51 条消息。
Node.js 服务端发布:
import Pusher from "pusher";
const pusher = new Pusher({
appId: process.env.PUSHER_APP_ID!,
key: process.env.PUSHER_KEY!,
secret: process.env.PUSHER_SECRET!,
cluster: process.env.PUSHER_CLUSTER!,
useTLS: true,
});
await pusher.trigger("private-tenant-org_42", "invoice.updated", {
invoiceId: "inv_17",
version: 4,
});
私有频道授权应由 Node.js 端点处理,在签名订阅前验证已认证用户。当功能集相对直接,固定套餐上限比用量公式更容易理解时,Pusher 是一个合适选择。
3. PubNub:最佳基于 MAU 的全球消息平台
PubNub 当前定价强调月度活跃用户,而不是连接分钟数或单独的消息量。
当前公开套餐包括:
- Free:$0,最高 200 MAU,面向开发的额度,1 GB 存储和 7 天历史。
- Starter:$98/月,含 1,000 MAU 和最多六个月消息存储。
- Pro:按量定价/定制,公开 MAU 示例大约为 10,000 MAU 约 $550/月,50,000 MAU 约 $2,100/月,大规模定制价格另议。
MAU 模式可以与按席位或活跃用户销售的 B2B SaaS 很好地对齐。连接分钟数平台对待偶尔上线的用户和每天在线八小时的用户差异很大;MAU 模式通常更容易做商业预测。
PubNub 拥有广泛的实时功能集:发布/订阅、在线状态、持久化、过滤、reactions、Chat SDK、Functions、审核、用户/频道管理和 Insights。
2026 年 Node.js 方面一个值得注意的变化是 JavaScript SDK 12.x。当前文档要求现代服务端路径使用 Node.js 22+。2026 年 6 月版本将传输层从 node-fetch + proxy-agent 改为 undici,SDK 12.0.0 不再支持 Node.js 18/20。
npm install pubnub
对于现有 Node.js 18/20 服务,在升级到 PubNub SDK 12 之前,先规划运行时升级。
4. Azure Web PubSub:最佳 Azure 原生托管 WebSocket
Azure Web PubSub 让 Node.js 应用避免直接运营 WebSocket 服务器集群,同时把业务逻辑保留在 Azure Functions、App Service、Container Apps、AKS 或普通服务中。
容量按单位计算。每个 Standard 或 Premium 单位支持最多 1,000 个并发客户端连接。Standard 目前最多支持 100 个单位;Premium 可以扩展得更高。Free 层支持 20 个并发连接和 20,000 条消息/天,因此仅适合开发。
Premium 增加了重要的生产能力:
- 99.95% SLA
- 可用区支持
- 全托管自动缩放
- 自定义域
- 异地复制
Azure 的实际单位价格由区域/协议/货币决定,因此生产采购应使用实时计算器,而不是照搬某个全球数字。
消息计费基于出站流量,使用 2 KB 消息单位。较大的负载会消耗多个单位。这印证了与 Ably/Pusher 相同的设计规则:广播小事件,而不是整个应用对象。
Azure 在 2026 年还增加了显著能力。Q1 引入了通配符分组角色模式,对分层多租户授权很有用。Q3 在公开预览中发布了 Web PubSub Chat,新增了房间、消息、成员、角色、历史记录、自动重连和消息恢复。
5. Amazon API Gateway WebSocket APIs:最佳 AWS 原生构建块
API Gateway WebSocket APIs 比 Ably、PubNub 或 Pusher 更低层。AWS 管理 WebSocket 端点和连接集群;你需要自行构建更高层的实时协议。
常见架构是:
browser ──> API Gateway WebSocket
├──> $connect -> Lambda
├──> $disconnect -> Lambda
└──> message route -> Lambda
│
v
DynamoDB connection registry
│
v
Node.js publisher ──> API Gateway Management API ──> connected clients
你仍然需要构建房间/频道、在线状态语义、持久历史记录、重放、重连行为、扇出批处理,以及死连接清理。
AWS 当前 US-East 定价示例为每百万条 WebSocket 消息 $1.00,每百万连接分钟 $0.25。AWS 公布的 1000 用户聊天示例在 API Gateway 层总计 $23.40/月,尚未计入 Lambda、DynamoDB、CloudWatch、传输和其他服务。
AWS 在 2026 年也改善了开发者体验。5 月 5 日,AWS SAM 新增原生 AWS::Serverless::WebSocketApi 支持,包括 $connect、$disconnect、$default、自定义路由、IAM/Lambda 授权、自定义域和路由设置。5 月 1 日,CloudFront 新增了对 VPC origin 的 WebSocket 支持,允许私有子网中的 ALB/NLB/EC2 origin 在 CloudFront 后提供 WebSocket 流量。
当 AWS 已经是你的平台,并且团队能够自行构建应用级实时状态时,使用 API Gateway WebSocket。
扇出成本是最常见的计费意外
设想一个有 5,000 名在线用户的仪表盘房间。服务端每秒发布一条更新:每天 86,400 次发布。但投递消息大约为 86,400 × 5,000 = 432,000,000 次投递/天。基础设施决策由扇出驱动,而不是发布次数。
- 不要广播没有人需要的更新。按租户、项目、房间或仪表盘限定订阅范围。
- 避免创建数百万个微小频道,却不了解提供方限制和频道分钟经济性。
- 尽可能批量处理高频信号。一个实时仪表盘可能不需要每秒 100 条独立的数据库变更;每秒一条聚合更新可能是更好的产品,也是便宜得多的传输方式。
租户授权是关键 B2B 边界
实时频道名通常包含业务标识:
tenant:org_42
project:prj_17
user:usr_9
浏览器不能任意选择访问权限。正确流程是:
browser ──> Node.js auth endpoint
├──> validate session
├──> resolve tenant membership
├──> resolve resource permission
└──> issue short-lived capability
不同提供方的机制不同——Ably capabilities、Pusher 私有频道签名、PubNub Access Manager、Azure 角色、API Gateway authorizer——但规则相同:授权属于可信的 Node.js 控制平面。
重连不是边缘情况
移动网络会断开。笔记本会休眠。浏览器会暂停标签页。企业代理会中断空闲连接。
生产环境的用户体验应假设:
connected ──> disconnected ──> reconnecting ──> recovered or resynced
即使提供方支持连接恢复,也应维护应用级重同步路径,以应对更长的中断,例如 GET /resource/current 或基于 cursor/version 的端点。
在事件中包含版本:
{ "type": "document.updated", "documentId": "doc_7", "version": 44 }
如果客户端最后看到版本 41,然后收到 44,它就知道需要重新拉取持久状态。
在线状态是昂贵状态
在线状态看起来很简单——“谁在线?”——但语义很困难。一个用户可能开了三个标签页。移动应用可能处于后台。网络可能消失 30 秒。一个房间可能有 20,000 个用户。
在线状态事件也会造成扇出风暴,因为每次加入/离开可能被投递给很多成员。如果 UI 只需要占用人数,在提供方支持时使用占用/计数原语,而不是完整成员列表。
聊天不只是发布/订阅
聊天需要持久历史记录、消息 ID、顺序、编辑、删除、reactions、已读标记、正在输入提示、审核、成员关系、角色和附件元数据。
如果聊天是核心,应比较更高层的产品,如 Ably Chat、PubNub Chat 和 Azure Web PubSub Chat,而不只是原始 WebSocket 传输。
不要在数据库提交之前发布
糟糕做法:
await realtime.publish("invoice.updated", payload);
await db.commit();
客户端可能收到一个从未真正持久化的事务事件。
同样脆弱:
await db.commit();
await realtime.publish("invoice.updated", payload);
……因为业务状态提交后发布可能失败。
对于重要事件,使用事务性发件箱:
database transaction
├──> update business row
└──> insert outbox event
│
v
background publisher ──> realtime platform
实时投递可以重试,而不会控制原始事务。
成本模型
收集这些输入:
- 月度活跃用户
- 峰值并发连接
- 平均连接小时/天
- 每天发布事件数
- 每个事件平均订阅者数
- 消息大小
- 活跃频道/房间
- 历史保留
- 在线状态使用
- 区域
- SLA 要求
然后估算:发布次数 + 订阅者投递次数 + 连接时长 + 频道时长 + 历史/存储 + 带宽。
示例:5,000 MAU,平均每天连接 2 小时,每月 200 万次发布,每次发布 4 个接收者。
大致消息操作数:200 万次入站发布 + 800 万次出站投递 = 1000 万次。连接分钟数:5,000 × 2 × 60 × 30 = 1800 万连接分钟。现在比较各提供方定价——某类负载下最便宜的供应商,在另一种负载下可能是最贵的。
什么时候自托管 WebSocket 更好
当用户主要在一个区域、并发可预测、协议语义简单、你已经运营 ECS/Kubernetes,或者托管扇出定价过高时,自托管可能是合理的。
典型架构:
Cloudflare / CloudFront ──> ALB ──> Node.js ws / Socket.IO fleet
├──> Redis adapter
├──> Kafka/NATS
└──> PostgreSQL
现在你需要自己负责连接均衡、重连行为、部署排水、共享状态、区域故障转移、DDoS 防护、容量和监控。要比较工程拥有成本,而不仅仅是 VM/Redis 账单。
什么时候 SSE 更好
当通信主要是服务端到浏览器,且不需要双向消息时,使用 Server-Sent Events。
合适的 SSE 使用场景:
- LLM token 流式输出
- 任务进度
- 报告生成
- 单个用户的实时日志
当客户端也需要发送实时事件,或需要房间、在线状态、多路复用和长连接双向交互时,使用 WebSocket。
最终推荐
对于 2026 年大多数 Node.js SaaS 应用:
- Ably 是最强的整体托管实时默认选择,当连接连续性、全球扇出、在线状态、恢复、历史记录和企业规模都很重要时。
- Pusher Channels 是最好的简单开发者优先选择,当固定套餐和私有/在线状态频道满足需求时。
- PubNub 是最强选择,当 MAU 计费与 SaaS 商业模式一致,且聊天/在线状态/消息功能是核心时。
- Azure Web PubSub 是自然的 Azure 原生选择,并且通过 2026 年托管 Chat 预览版变得更面向产品。
- Amazon API Gateway WebSocket APIs 是最好的底层 AWS 原生构建块,当团队能够自行负责房间、在线状态、历史、重放和连接注册表语义时。
架构规则比供应商更重要:
实时传输应当投影持久业务状态,而不是替代它。
将授权放在 Node.js 后端。使用短期客户端能力。刻意设计重连和重放。让处理器具备幂等性。控制扇出。保持消息小。在选定定价模式前,使用 connections × time × fanout × message size 对真实负载做基准测试。
这就是实时演示和实时 SaaS 平台之间的区别。