Realtime webhooks
发布(Publishing)将事件推送给客户端。Webhooks 则方向相反:当频道上发生事件时,Realtime 边缘节点会向你的端点 POST 一个签名事件。
你已经可以通过查询频道状态按需读取频道状态。Webhooks 让你在变更发生时立即收到通知,无需轮询:例如客户端订阅、成员关闭最后一个标签页、一个客户端向另一个客户端发送光标位置。
五个事件组
订阅一个或多个事件组:
| 组 | 回答的问题 | 投递内容 |
|---|---|---|
| realtime.channel_existence | 是否有人在监听? | realtime.channel_occupied、realtime.channel_vacated |
| realtime.presence | 谁在这里? | realtime.member_added、realtime.member_removed |
| realtime.connection_count | 有多少连接? | realtime.connection_count |
| realtime.cache_channels | 该频道是否需要数据? | realtime.cache_miss |
| realtime.client_events | 客户端在发送什么? | 每个客户端事件对应一个事件,以该事件命名 |
channel_existence 只报告频道生命周期的两个边界:从零连接变为一个连接时发送 channel_occupied,最后一个连接离开时发送 channel_vacated。中间的订阅者加入和离开不会产生任何事件,因此它是判断是否值得发布的低成本方式。
connection_count 需要在应用上启用连接计数。如果该设置被禁用,已订阅的组不会产生任何事件。
订阅端点
打开 Webhooks,创建或编辑一个端点,找到 Realtime events 部分。选择一个 Realtime 应用和要接收的组。
平台事件订阅在整个工作区范围内生效,而 realtime.* 订阅属于单个应用。创建后无法更改端点的 Realtime 应用,但可以更新其订阅的组。
平台事件和 Realtime 事件可以共用一个端点。例如,一个端点可以同时订阅 email.bounced 和 realtime.presence。两者使用同一个端点签名密钥。
Realtime 组目前仅支持在仪表板中配置。包含 realtime.* 事件类型的公开 POST /v1/webhooks 请求会被拒绝,因此请在仪表板中配置这些订阅。
投递的结构
每个 POST 包含一个事件,使用 Bird 的标准 webhook 信封格式:
代码示例
{
"data": { "channel": "presence-room-1", "member_id": "u_42" },
"timestamp": "2026-07-31T09:00:00Z",
"type": "realtime.member_added"
}type 标识所投递的事件。例如,realtime.presence 组投递 realtime.member_added 和 realtime.member_removed:
| 投递的 type | data 字段 |
|---|---|
| realtime.channel_occupied | channel |
| realtime.channel_vacated | channel |
| realtime.member_added | channel、member_id |
| realtime.member_removed | channel、member_id |
| realtime.connection_count | channel、connection_count |
| realtime.cache_miss | channel |
| realtime.<client event> | channel_name、event、data、connection_id,presence 频道还包含 member_id |
验证投递
Realtime webhooks 遵循 Standard Webhooks 规范,并包含 webhook-id、webhook-timestamp 和 webhook-signature 请求头。使用端点的签名密钥进行验证。
代码示例
import { BirdClient } from "@messagebird/sdk";
const bird = new BirdClient({
apiKey: process.env.BIRD_API_KEY,
webhooks: { secret: process.env.BIRD_WEBHOOK_SECRET },
});
app.post("/webhooks/bird", express.raw({ type: "*/*" }), (req, res) => {
const event = bird.webhooks.unwrap(req.body, req.headers);
res.sendStatus(200);
switch (event.type) {
case "realtime.channel_vacated":
stopExpensiveWorkFor(event.data.channel);
break;
case "realtime.member_removed":
markAway(event.data.member_id);
break;
}
});请验证原始请求体,因为解析并重新序列化 JSON 可能会改变已签名的字节。在 default 分支中处理未知事件类型,以免新类型导致端点出错。参阅验证 webhook 签名了解完整约定。
Presence 事件按成员计数
member_added 和 member_removed 跟随身份标识,因此与连接不是一一对应的。在三个标签页中打开你的应用的用户算作一个成员:
| 发生的事件 | Webhook |
|---|---|
| 第一个标签页订阅 | realtime.member_added |
| 第二个标签页订阅 | 无 |
| 第二个标签页关闭 | 无 |
| 最后一个标签页关闭 | realtime.member_removed |
使用 member_removed 检测某个身份标识何时离开频道。单个会话结束时,如果另一个会话仍然存在,不会触发该事件。要跟踪连接,请订阅 realtime.connection_count。参阅 Presence 频道。
Realtime webhook 投递行为
Realtime 投递遵循以下重试和可见性规则:
- 在持久化接收事件后立即返回 2xx,然后异步处理。
- 如果端点返回非 2xx 响应,Realtime 会以指数退避方式重试,最长持续 5 分钟。
- Realtime 事件不支持重放,也不会出现在端点的投递尝试日志中。
- 暂停端点会停止 Realtime 投递以及所有其他投递,重新启用后恢复。
投递是无序的,且不提供逐事件回执。将它们视为变更通知。使用查询频道状态在事件延迟或丢失后获取当前状态。
后续步骤
- 客户端事件是由你自行定义事件名称和载荷的组。
- Cache 频道介绍了如何处理 realtime.cache_miss。
- Webhooks 与事件涵盖了每种 Bird webhook 的端点设置、签名验证和密钥轮换。
相关资源
继续查阅此主题的文档、指南和示例。资源为英文。