系统监控:条件检测、告警聚合与恢复通知
系统监控由持续采集和规则评估驱动。用户登录监控页面只是查看结果,不承担触发检测的职责。服务无法处理登录请求时,独立监控仍应能发现故障。
示例规则是“某服务连续一段时间错误率超过阈值后触发告警,条件不再满足后按恢复规则解除”。阈值、观察窗口和持续时间需要根据流量与业务目标设置。
从失败日志推导持续检测
假设需求是“接口持续失败时通知值班人”。一条失败日志只能说明某次请求出错;它没有给出总请求数、持续时间和影响范围,直接发通知容易把一次偶发失败放大。
| 候选方案 | 能发现什么 | 需要补充的边界 |
|---|---|---|
| 发现错误日志就发送 | 单次具体错误 | 分母、持续性、重复与故障分组 |
| 周期探测接口 | 探测位置看到的可用性 | 不一定代表所有真实流量与用户地域 |
| 指标窗口判断并结合独立探测 | 持续错误、流量与可达性 | 采集缺失、低样本和检测链路自身健康 |
本篇用指标规则判断持续异常,再由通知系统负责路由与升级。它们可以部署在成熟监控平台中,不要求业务服务自己实现一套告警引擎;开发者仍要理解每一层承诺了什么。
检测、通知与人工响应时序
规则引擎维护故障状态,通知系统负责分组与路由,人工确认则是第三种事实。图中的通知系统包含实际采用的渠道及值班响应组件。
数据缺失需要独立规则判断,不应沿着“没有错误数据”直接进入恢复分支。无人响应升级由通知与值班组件按本轮状态继续推进。
监控需求与发现期限
示例要求对持续错误率异常生成可定位的故障通知,同时区分业务无流量、采集链路中断和真实故障。普通用户不登录时检测仍继续,运维打开页面时看到的是已经评估过的状态。
| 需求 | 示例约定 | 实现约束 |
|---|---|---|
| 检测范围 | 按集群与服务判断 | 指标标签、聚合与通知路由保持对应 |
| 短暂失败 | 需要持续满足条件 | pending 与 firing 分离 |
| 通知时效 | 计入采集、评估、持续确认与分组等待 | 不把某个单独间隔当总延迟 |
| 值班无人响应 | 达到规则后升级到备用负责人 | 升级状态独立记录 |
| 系统恢复 | 保留完整故障轮次与恢复结果 | 不能只删除当前告警 |
检测条件与通知条件
| 环节 | 示例 | 需要避免的问题 |
|---|---|---|
| 采集 | 周期拉取接口成功数、错误数和耗时 | 没采到数据却误认为零错误 |
| 判断 | 在固定窗口计算错误率 | 小样本产生剧烈抖动 |
| 持续确认 | 条件持续满足才进入触发态 | 单次短暂波动就通知 |
| 通知 | 告警状态变化后交给通知系统 | 每次评估都重新发短信 |
| 恢复 | 连续恢复后关闭告警 | 围绕阈值反复开关 |
“采集失败”“数据缺失”和“检测到错误”需要不同结果。阈值计算还要限定最低样本量,或对低流量接口采用适合的其他信号。
数据身份与开发组件
| 组件或记录 | 输入与职责 |
|---|---|
| 指标采集器 | 采集计数器、耗时和目标可达性,保留采集时间 |
| 规则定义 | 表达式、标签、持续时间、负责人规则和配置版本 |
| 规则评估实例 | 规则身份与标签指纹、评估后 inactive/pending/firing、状态变化时间 |
| 告警事件 | 已触发的故障轮次、标签指纹、firing/resolved、触发与恢复时间 |
| 故障通知记录 | 告警轮次、分组、渠道、阶段、发送和确认结果 |
| 操作 API | 查询、确认、静默、规则修改;校验权限并审计 |
指标系统负责计算规则,通知系统负责去重、分组与路由。采用 Prometheus 与 Alertmanager 时,需要区分以下三层:
- 规则评估完成后的状态:
inactive、pending、firing;可对照 Prometheus v3.5.0 的规则状态定义。尚未完成评估或数据缺失不能直接推断服务正常。 - Alertmanager 通知中的告警状态:
firing、resolved,表示故障是否恢复,参见通知模板中的 Status。它不是渠道投递结果。 - 渠道投递状态:是否待发、已提交、失败或收到回执,按共用通知约定分别记录;人工确认另有身份与时间。
自建系统可以保留恢复后的告警事件用于审计,但不能把通知层的 resolved 写成 Prometheus 原生规则状态,也不能用单个 sent 字段同时表示故障、投递和人工响应。
一条检测规则怎样落地
以下是 Prometheus 规则片段,假定应用提供带 cluster、service、code 标签的 http_requests_total。阈值、窗口和样本量都是示例:
groups:
- name: service-errors
interval: 30s
rules:
- alert: ServiceHighErrorRate
expr: |
(
sum by (cluster, service) (
rate(http_requests_total{code=~"5.."}[5m])
)
/
sum by (cluster, service) (
rate(http_requests_total[5m])
)
) > 0.05
and on (cluster, service)
sum by (cluster, service) (
increase(http_requests_total[5m])
) > 100
for: 2m
keep_firing_for: 1m
labels:
severity: pagefor 要求表达式持续满足后才进入触发态,keep_firing_for 让条件最后满足后的指定时间内继续保持触发,减少短暂波动造成的恢复抖动;完整语义见 Prometheus 告警规则。目标完全没数据时,这条错误率规则不能替代缺失或不可达检测,需要单独的规则。
再用 Alertmanager 的路由配置分组等待与重复周期,例如按 cluster、service、alertname 分组;具体配置项见官方配置说明。分组等待、重复通知和人工确认是不同机制,人工确认后的升级策略需要接入值班系统或自己的状态服务。
上面的条件包含三类判断:错误率超过阈值、请求样本足够、条件持续成立。少掉样本约束时,一次请求失败就可能达到 100%;少掉持续条件时,短暂波动就可能触发通知。5 分钟窗口本身也不意味着固定延迟 5 分钟才开始检测。
1000 个实例同时报警
上面的 ServiceHighErrorRate 已按 cluster, service 聚合,每个标签组合产生一个告警实例,不会保留每台应用实例的告警身份。本节另外讨论实例级检测:例如应用主动探测数据库,并上报带 cluster、service、instance 标签的 db_connectivity_ok,成功为 1、失败为 0:
- alert: InstanceDatabaseUnavailable
expr: db_connectivity_ok == 0
for: 2m
labels:
severity: page这条规则保留实例标签,数据库不可达时,1000 个应用实例可能产生各自的告警。指标缺失仍需另设采集或目标不可达规则,不用缺失值代表探测成功。如果逐实例通知值班人,会掩盖真正的故障。
对于这类实例级规则,应保留实际触发的各实例告警,再按集群、服务、告警名称等属性分组。对已经确认的上游故障,可以抑制与其关联的下游告警;同一组重复评估只更新活跃状态。若只采用前面的服务级聚合规则,则通过保留的实例指标或日志定位细节,不能声称通知系统还持有被聚合掉的实例告警。
Prometheus 的 Alertmanager提供去重、分组、路由、静默和抑制,官方文档也以大量实例同时报警说明分组的价值。
分组不等于把所有故障混在一起。不同租户、不同故障域和不同值班负责人,应保留必要的隔离与路由。
谁收到、什么时候再次提醒
通知规则需要确定负责人、备用负责人、首次分组等待时间、持续故障的重复提醒间隔,以及无人确认时的升级策略。
同一个持续故障可以按规则再次提醒,因此业务键要包含告警轮次与通知阶段,而不是永久禁止同一告警名称再次发送。故障恢复后再复发,属于新的轮次。
分组等待会增加首次通知延迟,应计入业务允许的发现和通知时间。紧急故障可以采用更短等待,但仍要控制同组重复消息。
通知通道故障怎么办
邮件、短信或值班服务失败时,只重试对应通知记录,不把检测结果改回正常。配置升级渠道时明确触发条件,避免多个渠道互相重试形成消息放大。
监控系统自身也需要可观察性,例如规则评估是否推进、最老待发送告警年龄、通知失败率和外部心跳。部署在同一故障域的“自检成功”不足以证明外部用户可达。
通知与升级处理顺序
规则持续成立,产生 firing 告警
通知路由按故障域与负责人分组
在分组窗口结束后保存并提交本阶段通知
渠道失败:只重试当前通知,不重新创建故障
值班人确认:记录告警轮次与确认身份
达到升级时间:重新核对仍在故障、尚未确认,再安排升级
收到恢复:结束故障轮次,停止尚未提交的旧升级动作恢复、确认与升级可能并发。升级任务发送前复核当前轮次;对已经提交的外部通知保留结果,不能认为标记 resolved 就撤回了已发短信。
一次故障从发现到恢复
以下是设计时序样例:规则每 30 秒评估,持续确认 2 分钟,示例分组等待 30 秒。具体时刻取决于采集和评估对齐,不构成严格发现时延保证。
| 时刻或操作 | 规则与通知状态 | 应采取的动作 |
|---|---|---|
| 10:00 首次满足错误率与样本条件 | pending | 记录候选,不立即发首条通知 |
| 后续评估连续满足,达到 2 分钟 | firing | 进入通知分组窗口 |
| 分组窗口结束 | 首次通知已提交 | 保存渠道结果,等待独立的人工确认 |
| 值班人确认故障 | 仍为 firing,但已有确认 | 依据策略停止未提交的无人响应升级 |
| 条件不再满足并经过恢复保持时间 | 规则回到 inactive;通知层事件为 resolved | 结束本轮,按策略通知恢复 |
假如通知请求成功后进程退出,恢复时应查询或重试同一通知身份,不再次创建一个“新故障”。假如没有数据,则应由数据缺失规则说明检测盲区,不能把它等同于真实业务恢复。
应验证的结果
| 场景 | 预期结果 |
|---|---|
| 1000 个实例受同一根因影响 | 保留实例明细,值班人收到可定位的聚合通知 |
| 单实例偶发失败 | 按持续条件判断,不立即形成告警风暴 |
| 指标没有更新 | 进入数据缺失判断,不伪装成正常 |
| 通知通道不可用 | 告警事实仍保留,发送按规则恢复或升级 |
| 故障恢复又复发 | 形成可区分的新告警轮次 |
| 规则修改后旧评估结果迟到 | 记录规则版本,不让旧结果覆盖新判断 |
| 值班确认与升级任务同时到达 | 按本轮最新状态判断,记录是否已提交升级 |
| 监控数据库与业务同时不可达 | 独立心跳或外部探测仍能暴露监控盲区 |
验收时从真实故障起点计算发现与通知延迟,分别记录采集、评估、持续确认和渠道提交时间。发送请求成功只是渠道提交结果,不等于值班人已确认。
腾讯云告警收敛的分组与等待窗口
腾讯云可观测平台的收敛规则文档展示了一个可配置产品方案:根据策略、指标、事件或资源维度合并告警,并分别设置首次聚合等待与后续通知频率。该文档中的规则仅支持单一策略内收敛,因此不能假设跨策略的根因抑制也已经自动完成。
对应到本文,1000 个实例告警之前,应先确定分组是在表达“同一个故障”还是“同一接收人的摘要”。按主机分组便于看单机问题,按指标分组便于看共同异常,但都不天然证明同一根因。分组键需要带上业务与环境边界,避免把生产支付故障和测试环境噪声混为一条。
等待窗口也是响应时间的一部分。本文建议把检测等待、聚合等待和渠道提交延迟分别计量;需要立即通知的严重故障,应选择与响应目标匹配的策略,不能在增加聚合窗口后仍宣称原来的发现时效不变。已收敛通知中的成员变化也要保留,单台恢复不能把整组仍在发生的故障标记为结束。
美团 AIOps:告警聚合之后还要关联事件证据
美团的 AIOps 事件管理实践讨论了结合指标、链路、日志和变更分析故障,以及历史事件推荐。文章指出,粒度很粗的通用告警可能对应不同根因,仅有相同告警并不足以认定是相同故障。
对本文监控系统,可以先保存原始告警,再建立带有服务、环境、时间窗口及关联证据的事件记录。相同的 HTTP 5xx 告警可以用于召回历史故障,但不能直接触发旧故障使用过的重启或回滚动作。自动处置还应检查当前发布版本、影响范围和动作授权,处置后验证业务指标是否恢复。
火山引擎:告警事件生命周期与通知排查
火山引擎的告警事件说明将首次触发到恢复作为一个事件,恢复后再次触发产生新事件。这为本文的 episode 设计提供了真实产品对照。其文档也有事件保留和展示数量限制,长期审计不能仅依赖控制台当前可见列表。
告警常见故障文档分别处理未触发、已触发却未收到通知等情况。应用据此可以把排查入口拆成规则评估、事件建立、通知提交、渠道结果和人工响应,避免一收到“没看到短信”的反馈就重建故障事件。
1000 台实例同时告警时,一条聚合通知下应保留成员事件及各自恢复情况。若需要更长的复盘周期,应按所用产品支持的方式归档必要事件与处置证据;发送成功仍需与用户实际收到或确认区分。
参考资料
Prometheus v3.5.0:规则状态定义:rules/alerting.go
Prometheus:Notification template reference
美团技术团队:AIOps 在美团的探索与实践——事件管理篇
火山引擎官方文档:全栈可观测平台:告警事件
火山引擎官方文档:云监控:告警常见故障
腾讯云官方文档:可观测平台:新建收敛规则
Prometheus:Alertmanager
Prometheus:Instrumentation
Prometheus:Alerting rules
Prometheus:Alertmanager configuration