Skip to content

事件总线 ​

当有值得知道的事情发生时,面板会发出一个事件,并投递给每个订阅了它的订阅者:Webhook、插件、Telegram 聊天和电子邮件地址。本页说明投递是如何完成的,以及接收方可以依赖什么。事件列表及其载荷见 事件目录;设置 Webhook 见 Webhook 与事件。

事件如何投递
一次变化
用户、节点、管理员或面板
发件箱
每个订阅者一次投递
投递
按顺序,可重试
Webhook
签名的 POST
插件
清单中声明的事件
Telegram、邮件
面向人,按角色过滤

点击任意方框,查看那里发生了什么。

事件与 API

事件报告变化 ​

事件表示某样东西发生了变化:某个账户达到了额度、某个节点停止应答、某位管理员从新地址登录、一次备份完成。持续存在的状态只在开始时报告一次,在合适的情况下结束时再报告一次(节点磁盘快满,然后恢复)。只是被停用的节点不会在每次心跳时都发出事件。

必须在重启后保留的警告(例如账户的到期警告或插件的健康状态)记录在数据库中,所以重启面板不会重复它们中的任何一个。少数按定时器判断的状态(例如代理商超出配额)记录在内存中,重启后每个可能重复一次。

四个类别 ​

事件名称的第一个词说明它涉及什么,这也决定了谁可以收到它:

类别涉及示例
user.*一个账户;总是写明拥有它的管理员user.quota_reached、user.expiring、user.first_fetch
node.*一个节点node.disconnected、node.disk_high、node.rejections_high
admin.*一个运营者账户admin.login_new_ip、admin.resale_cap_reached
panel.*安装本身;从不写明任何账户panel.backup_failed、panel.cert_expiring、panel.addon_unhealthy

因为每个 user.* 事件都写明了其所有者,通知可以发给该客户所属的代理商。panel.* 事件永远不会到达绑定在代理商身上的订阅者。

发件箱 ​

发出一个事件是一个数据库事务:

  1. 事件被写入发件箱一次。
  2. 对每个已启用、事件过滤器需要它、且其所有者可以看到它的订阅者,在旁边写入一行投递记录。

没有订阅者需要某个事件时,什么都不写,所以没有订阅者的安装会保持一张空表。由于事件和它的投递是一起写入的,事件永远不会只投递了一半:要么每个订阅者都有待投递的记录,要么都没有。

事件和投递按事件保留期保存,默认 7 天,最长 90 天,并且是每份备份的一部分。

投递与重试 ​

面板中的一个后台工作进程负责发送到期的投递:

  • 每个订阅者按顺序。 每个订阅者的投递一个接一个地发送,所以接收方看到事件的顺序与发生的顺序一致。不同的订阅者互不等待。
  • 失败会重试,延迟每次翻倍,从 30 秒开始,上限一小时,并带有少量随机性,避免重试同时到达。
  • 10 次尝试后投递即作废。 它会连同最后一次应答保留在列表中,重新发送 可手动重试。
  • 订阅者只有在失败既连续很长、又超过一天时才会被停用。 宕机一小时、积压的投递正在对它重试的接收方不会被停用。重新启用它会让计数从头开始。
  • 不跟随重定向。

发送测试事件 会立即发送 panel.ping 并显示接收方的应答。

信封 ​

Webhook 收到一个带 JSON 正文的 POST:

json
{
  "v": 1,
  "id": 1842,
  "event": "user.quota_reached",
  "time": 1791711000,
  "data": { "userId": 57, "name": "ali", "adminId": 3 },
  "recipients": [3]
}

id 是事件自己的 id,对每个订阅者、每次重试都相同。time 以 Unix 秒为单位。recipients 出现时,列出该事件涉及的管理员。

它带有三个头部:

头部携带内容
X-Nexora-Event事件名称
X-Nexora-Delivery投递 id;重试时会重复,所以接收方按这个 id 丢弃重复项
X-Nexora-Signature一个时间戳,以及用订阅者密钥对时间戳和正文计算的 HMAC-SHA256

接收方用创建订阅者时只显示过一次的密钥校验签名。从备份恢复时,投递表也会一起恢复,所以恢复后投递 id 可能重复:跨恢复保存 id 的接收方应在收到 panel.restore_applied 时从头开始。

精简的载荷 ​

载荷携带 id、名称和变化的内容,从不携带凭据:没有密码、密钥、订阅令牌或链接。需要更多信息的接收方用自己的令牌、在自己的权限下从 API 读取。

  • 批量操作和批量创建只发出一个汇总事件,而不是每个账户一个。
  • panel.settings_changed 写明设置项,从不写明它的值。

谁可以在哪里订阅 ​

  • 你手动添加的 Webhook 不能指向面板自己的网络:无论名称解析到什么,面板连接时都会拒绝回环地址、私有地址及类似地址。
  • 插件的 Webhook 属于它的 API 令牌。 它只收到你从其清单中批准的事件,可以访问在私有网络上与面板并排运行的插件,并在插件暂停期间保持静默。

面向人的渠道 ​

Telegram 聊天和电子邮件地址是人,不是程序。总线把每次投递交给 Telegram 或电子邮件发送器,而不是发 POST,重试方式相同,并先进行过滤:

  • 聊天或地址只收到其账户角色可以读取的内容。 代理商的聊天只收到有关自己客户的消息,别无其他。
  • 已关闭的服务什么都不投递。
  • 电子邮件地址必须先确认,才会向它发送任何内容。

参见 Telegram 和 邮件。

总线作为健康信号 ​

一次永远到不了的投递,对接收方什么也说明不了。因此面板始终在其指标端点上导出待投递、已投递和已作废投递的数量,以便针对作废投递的告警能够触发;参见 监控与指标。

文字与图片采用 CC BY 4.0 许可。