实时推送 Realtime
实时推送目前处于 Private Alpha 阶段:
- 功能仍在开发中,仅对受邀用户开放,需申请开通后使用。
- 接口、参数和控制台行为在正式发布前可能发生不兼容变更。
- 不提供 SLA,请勿用于生产链路。
申请开通或反馈问题,请联系你的商务经理或提交工单。
实时推送让应用在数据或用户状态发生变化时立即得到通知,无需频繁轮询数据库,也无需自行搭建 WebSocket 服务、连接管理、断线重连和消息路由。
它适合聊天、协同编辑、在线成员列表、订单状态更新、实时看板和通知提醒等场景。浏览器、Node.js 和微信小程序均可通过 JavaScript SDK 的 app.realtime() 使用。
核心概念
频道
**频道(Channel)**是客户端收发实时事件的基本单位,可以理解为一间有名字的房间,例如 room:123。加入同一频道的客户端可以接收相同的广播消息和在线状态。
频道可以是公开频道或私有频道。私有频道会根据 realtime.messages 表上的 RLS 策略检查客户端是否有权加入、发送和接收消息。
三种实时能力
| 能力 | 工作方式 | 典型场景 | 使用指南 |
|---|---|---|---|
| Broadcast | 在频道内发送自定义的低延迟消息,不要求先写入业务表 | 聊天消息、输入状态、协作光标、业务通知 | Broadcast |
| Presence | 追踪频道内的客户端及其自定义状态 | 在线名单、协作成员头像、当前活动页面 | Presence |
| Postgres Changes | PostgreSQL 表发生 INSERT、UPDATE 或 DELETE 后,将变更推送给订阅者 | 订单状态、消息列表、实时看板 | Postgres CDC |
三种能力共用频道和 WebSocket 连接,但解决的问题不同:
- 数据发生变化时更新界面,使用 Postgres Changes。
- 客户端之间传递临时消息,使用 Broadcast。
- 展示谁在线以及每个人的状态,使用 Presence。
watch() 的区别文档型数据库使用 collection.watch() 监听集合变化,见文档型数据库实时推送。app.realtime() 面向频道消息、在线状态和 PostgreSQL 表变更,两者不能互相替代。
开始使用
使用前请确认:
- 当前环境已开通实时推送。
- 应用已初始化 CloudBase JavaScript SDK,并取得可用的客户端访问密钥。
- 使用 Postgres Changes 时,目标表已加入发布,并已配置表权限和 RLS 策略。
- 使用私有频道时,
realtime.messages已配置相应的 RLS 策略。
下面的示例创建一个频道,接收并发送 Broadcast:
import cloudbase from "@cloudbase/js-sdk";
const app = cloudbase.init({
env: "your-env-id",
accessKey: "your-publishable-key",
});
const realtime = app.realtime();
const channel = realtime.channel("room:123");
channel.on("broadcast", { event: "message-created" }, (payload) => {
console.log("收到消息", payload);
});
channel.subscribe(async (status, error) => {
if (status === "SUBSCRIBED") {
await channel.send({
type: "broadcast",
event: "message-created",
payload: { text: "Hello" },
});
}
if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") {
console.error(status, error);
}
});
使用完毕后取消订阅并移除频道,避免连接残留:
await channel.unsubscribe();
await realtime.removeChannel(channel);
初始化、按需引入和连接管理见快速开始。
在控制台中配置和调试
打开环境后,进入 PostgreSQL > 实时推送。如果当前环境尚未开通,页面会显示开通提示。
管理表变更发布
**发布(Publication)**是 PostgreSQL 的数据库级对象,用来决定哪些表的哪些操作可以产生变更事件。
发布与数据库对象的关系如下:
- 一个数据库可以有多个 Schema。
- Schema 用于组织表、视图和函数,业务表通常位于
public。 - 一个发布可以从不同 Schema 中选择多张表。
INSERT、UPDATE、DELETE、TRUNCATE开关对发布中的全部表统一生效。
系统预置 cloudbase_realtime 发布供 Postgres Changes 使用。控制台的发布列表会显示名称、系统 ID、四种操作开关和已加入的表数量。系统托管的发布会带有用途说明,请勿手动删除关联的复制槽。
点表数量可以进入表管理。页面会列出当前 Schema 下的全部表:
- 开关打开:表已加入当前发布。
- 开关关闭:表尚未加入,可以在这里开启。
- 开关禁用:表属于
realtime、auth等受保护的系统 Schema,不能修改。
发布配置变更约 10 秒后生效。开启一张表时,系统还需要为 Realtime 服务角色授予读取权限;如果授权失败,客户端可能订阅成功但收不到变更。
使用调试器验证链路
调试器是控制台内置的 Realtime 客户端,无需编写代码即可验证频道、权限和事件过滤条件。
你可以:
- 加入公开或私有频道,并在完成后离开频道。
- 使用匿名用户、已登录用户等身份验证 RLS 策略。
- 分别监听 Broadcast、Presence 和 Postgres Changes。
- 按 Schema、表和行过滤表达式筛选 Postgres Changes。
- 查看消息类型、时间和完整 JSON Payload。
- 发送一条自定义 Broadcast,检查同频道客户端能否收到。
应用接入前,建议先在调试器中使用与真实客户端相同的身份和过滤条件完成验证。
配置访问策略
实时推送有两套彼此独立的授权方式:
- Broadcast 和 Presence:私有频道使用
realtime.messages表上的 RLS 策略。 - Postgres Changes:使用被订阅业务表自身的表权限和 RLS 策略。
Broadcast 和 Presence
realtime.messages 已由系统开启 RLS。不要执行 ALTER TABLE realtime.messages ENABLE ROW LEVEL SECURITY,也不要在受保护的 realtime Schema 中创建或修改系统表。你只需要在 PostgreSQL > 访问控制 > 策略 中为 realtime.messages 创建 Policy。
Policy 使用的数据库操作决定允许的行为:
| 数据库操作 | 控制的行为 |
|---|---|
SELECT | 接收 Broadcast 或 Presence |
INSERT | 发送 Broadcast,或通过 track() 发布 Presence |
realtime.messages.extension 用于区分消息类型:
- Broadcast 的值是
broadcast。 - Presence 的值是
presence。
下面的策略只允许已登录用户在 room:123 中接收 Broadcast 和 Presence:
CREATE POLICY "authenticated can receive room events"
ON realtime.messages
FOR SELECT
TO authenticated
USING (
realtime.messages.extension IN ('broadcast', 'presence')
AND realtime.topic() = 'room:123'
);
再创建一条 INSERT 策略,允许已登录用户在同一频道中发送 Broadcast 和发布 Presence:
CREATE POLICY "authenticated can send room events"
ON realtime.messages
FOR INSERT
TO authenticated
WITH CHECK (
realtime.messages.extension IN ('broadcast', 'presence')
AND realtime.topic() = 'room:123'
);
realtime.topic() 返回客户端当前要加入的频道名称。实际业务通常不应把频道名直接写死,而是结合成员关系表判断当前用户是否属于该频道。例如,假设 public.room_members 保存了 topic 和 user_id:
EXISTS (
SELECT 1
FROM public.room_members
WHERE room_members.topic = realtime.topic()
AND room_members.user_id = (SELECT auth.uid())
)
将这段条件与 extension 条件组合,即可让用户只访问自己加入的频道。也可以通过下面的表达式读取 JWT 中的自定义字段,加入部门、租户或角色等判断:
current_setting('request.jwt.claims', true)::json ->> 'your_claim'
数据库策略配置完成后,客户端还必须将频道设为私有频道:
const channel = realtime.channel("room:123", {
config: { private: true },
});
如果需要强制所有频道都经过 RLS 检查,请在实时推送设置中关闭允许公开频道。关闭后,没有设置 private: true 的频道会被拒绝。
客户端加入频道时,服务端会计算并缓存它的访问权限。修改 Policy 或移除用户的频道成员关系后,已经连接的客户端可能继续保留原权限,直到客户端重新连接、提交新的 JWT 或原 JWT 过期。
Postgres Changes
Postgres Changes 不使用 realtime.messages 的 Policy。每条数据库变更都会根据被订阅业务表自身的 RLS 策略,判断当前订阅者能否读取这一行。
要让客户端收到表变更,请同时确认:
- 目标表已加入
cloudbase_realtime发布。 - 订阅角色对目标表有
SELECT权限。 - 目标表已开启 RLS,并有 Policy 允许当前用户读取对应的数据行。
公开频道和私有频道都可以订阅 Postgres Changes,频道的 private 配置不会绕过业务表 RLS。
请遵循最小权限原则,不要仅为了调试而长期保留允许所有用户访问所有频道或数据行的策略。Postgres Changes 的完整表权限与 RLS 配置见数据库侧准备。
调整服务设置
设置页用于管理项目级运行参数,包括:
- 启用或停用实时推送服务。
- 是否允许公开频道。
- 授权检查和 Postgres Changes 使用的数据库连接池大小。
- 最大并发客户端数、总事件速率和 Presence 事件速率。
- 单条消息的最大负载。
保存设置会断开当前已连接的客户端。调整连接池和限额前,请结合数据库连接上限和实际业务流量评估,避免实时推送与业务 SQL 争抢资源。
监控与排查
开通后,可以在实时推送监控中观察连接数、Broadcast、Presence、Postgres Changes、频道加入次数、消息负载、数据库广播延迟和私有频道 RLS 耗时。
接口访问监控用于查看 WebSocket 建连和 HTTP Broadcast 的请求量、错误数、响应时间及热门路径。出现异常时,可以先判断问题来自建连、消息发送、数据库变更还是权限检查,再结合日志进一步定位。
常见问题:
| 现象 | 检查项 |
|---|---|
| 页面显示未开通 | 确认当前环境已开通实时推送 |
| Postgres Changes 订阅失败 | 确认表已加入发布,且订阅角色有表的 SELECT 权限 |
| 订阅成功但收不到表变更 | 检查业务表 RLS 是否放行当前用户,并等待发布配置生效 |
| 私有频道无法加入或收发消息 | 检查频道配置和 realtime.messages 的 RLS 策略 |
| 高并发时连接或消息被拒绝 | 检查连接池、并发客户端数和事件速率限制 |
更多客户端状态和错误处理方式见快速开始。