通知架构
一条通知经过三个对象:通知规则决定发给谁,媒介决定怎么发,模板决定发什么;三者靠媒介类型对上,缺一环通知就静默消失。
这页办完你会知道:一条告警事件从产生到「手机响了」,中间经过哪三个对象、 它们各自负责什么、靠什么字段连起来,以及哪一环缺了会让通知悄无声息地消失。
三个对象
| 对象 | 菜单 | 回答的问题 | 谁来配 |
|---|---|---|---|
| 通知媒介 | 告警通知 → 通知媒介 | 怎么发:往哪个 URL 发、用什么 HTTP 方法、请求体长什么样、超时和重试多少 | 管理员配一次,全站复用 |
| 消息模板 | 告警通知 → 消息模板 | 发什么:把事件字段渲染成一段文本 | 一般用内置的,要改文案时克隆一份 |
| 通知规则 | 告警通知 → 通知规则 | 发给谁、什么条件下发:选媒介 + 模板,填这一次的机器人 token / 接收人,再加级别和标签筛选 | 用哪个群、发给哪个团队,由用这条规则的人配 |
关键的分工是:密钥不放在媒介里,放在通知规则里。
一个「钉钉」媒介被十个业务组共用,每条通知规则填自己的 access_token,
互不干扰,也不用为每个群建一个媒介。邮件和短信是例外——SMTP 服务器地址、
云厂商 AK/SK 属于全站配置,写在媒介上。
从事件到消息的一次投递
告警规则判定出事件,并带着它挂着的通知规则 id 列表
│
└─ 逐条通知规则:
1. 跑这条通知规则上挂的事件处理工作流(可选)
└ 工作流把事件丢弃了 → 这条规则到此为止
2. 恢复事件且规则不通知恢复 → 跳过
3. 逐条「通知配置」:
a. 匹配筛选条件:时段 → 级别 → 标签 → 属性,四项全过才继续
b. 按 channel_id 取媒介,按 template_id 取消息模板
媒介找不到 / 模板找不到 → 丢弃,并写一条失败的通知记录
c. 用模板渲染出 $tpl.title / $tpl.content 之类的字段
d. 把 $tpl、$params、$sendtos 填进媒介的 URL、请求头、请求体,发出去
e. 无论成败,写一条通知记录
有两点容易搞错:
- 筛选是「与」的关系,但空值的含义不一样。 时段、标签、属性留空表示不限制; 级别留空表示匹配不到任何事件,等于把这条通知配置停用了。
- 屏蔽规则和订阅规则不在这条链路里,它们发生在事件落库那一步,比通知规则更早。 完整的先后顺序见降噪与路由模型。
模板和媒介靠「媒介类型」字符串对上
消息模板上有一个 notify_channel_ident(界面上叫媒介类型),媒介上有一个同名字段。
通知规则里选好媒介之后,模板下拉框只列出媒介类型相同的模板——这是一次字符串匹配,
不是外键。
这解释了三件事:
- 内置的 20 个消息模板覆盖了 20 种媒介类型(
dingtalk、wecom、feishucard、telegram、slackwebhook、discord、jira、email、tx-sms……), 但开源版只内置了 6 个媒介。多出来的模板不是摆设:你自己建一个媒介类型是slackwebhook的媒介,那份内置模板立刻就能选了。 - 模板里写的字段名(
title、content、subject、incident)必须和媒介请求体里的{{$tpl.xxx}}对得上。对不上的那个字段渲染成空,消息发出去了但内容缺一块。 - 换媒介会清空已选的模板和参数——因为原来那份多半配不上新媒介。
有三类媒介不吃模板
request_type 是 flashduty 或 pagerduty 的媒介,以及标识为 callback 的媒介,
后端直接从事件字段拼 payload,不渲染消息模板;界面上也因此不给它们显示「消息模板」下拉框。
其余媒介没选模板就整条丢弃,并写一条 message_template not found 的失败通知记录——
这是「配好了却一条都收不到」最常见的原因。
一条通知规则里可以有多条通知配置
「通知配置」是可以加多条的,每条有自己的媒介、模板、接收人和筛选条件。 一条规则里放三条配置,就能做出这种效果:
| 通知配置 | 媒介 | 适用级别 | 适用时段 |
|---|---|---|---|
| 1 | 电话 | S1 | 不限 |
| 2 | 钉钉群 | S1、S2 | 不限 |
| 3 | 邮件 | S3 | 周一至周五 09:00–18:00 |
同一个事件会被逐条配置独立匹配,命中几条就发几条。
开源版没有的
「通知升级」(长时间未恢复就换个媒介再叫一次)和「通知聚合」(把同类事件合并成一条) 开源版不提供,通知规则表单里没有这两块,后端也不处理。 要压噪音,开源版的手段是屏蔽规则、订阅的级别过滤,以及在事件处理工作流里丢弃事件。