从设计到落地的完整实践
案例背景
某互联网公司(以电商平台为例)业务规模快速增长,微服务数量超过200个,日均产生日志量达50TB,运维团队频繁面临以下问题:

- 告警延迟:故障发生时,平均15分钟后才收到通知
- 告警风暴:一次故障触发300+条相关告警,人工排查困难
- 误报率高:约40%的告警无需处理,造成团队“狼来了”疲劳
- 租户隔离:多个业务线共用监控系统,需要相互隔离
为此,团队决定构建一套智能告警系统,目标是:1分钟发现、3分钟定位、10分钟恢复。
告警系统整体架构
1 告警系统在监控体系中的位置
┌─────────────────────────────────────────────────────┐
│ 告警系统整体架构 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 数据采集层 │──▶│ 数据处理层 │──▶│ 告警判定层 │ │
│ └──────────┘ └──────────┘ └────┬─────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 通知触达层 │◀──│ 事件管理层 │◀──│ 告警去重层 │ │
│ └──────────┘ └────┬─────┘ └──────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ 告警协同/运维大盘 │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────┘
2 核心组件
| 组件 | 技术选型 | 职责 |
|---|---|---|
| 数据采集 | Prometheus + Grafana Agent | 采集指标、日志、链路数据 |
| 数据处理 | Kafka + Flink | 实时流式处理、规则匹配 |
| 告警规则引擎 | Prometheus AlertManager + 自研 | 阈值检测、智能降噪 |
| 存储 | ES + ClickHouse | 指标存储与告警历史查询 |
| 通知触达 | 自研 Notify Service | 多渠道通知、排班路由 |
| 协同 | 自研 OnCall 平台 | 告警认领、升级、复盘 |
告警生命周期管理
一个完整的告警从产生到关闭,经历以下状态流转:
┌────────────┐
│ 正常状态 │
└─────┬──────┘
│ 触发条件满足
▼
┌────────────┐
│ PENDING │◀── 等待确认期
└─────┬──────┘ (默认1分钟)
│ 超过等待期
▼
┌────────────┐
│ FIRING │──▶ 发送通知
└─────┬──────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ ACK(认领)│ │ 自动恢复 │ │ 升级为故障 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 处理中 │ │ CLOSED │ │ INCIDENT │
└────┬────┘ └─────────┘ └────┬────┘
│ │
▼ ▼
┌─────────┐ ┌─────────┐
│ RESOLVED │ │ 复盘/改进 │
└─────────┘ └─────────┘
关键设计点:
- 每个告警有
alert_id贯穿全生命周期 - 重复告警通过
fingerprint关联到同一alert_id - 告警状态变化全部通过事件总线广播
关键设计:告警降噪与收敛
这是本案例最具价值的部分,针对“告警风暴”问题,设计了四层降噪机制:
1 规则层降噪
图:告警降噪流水线
原始告警
│
▼
┌──────────────────────────────────────────┐
│ ① 相似告警聚合(指纹计算) │
│ ───────────────────────────────────── │
│ 指纹 = hash(指标名 + 主机 + 告警类型) │
│ 相同指纹的告警合并为一条 │
└──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ ② 告警风暴抑制(TopN策略) │
│ ───────────────────────────────────── │
│ 当同一服务告警 > 50条/分钟时 │
│ 仅保留 Top3,其余标记为 "被抑制" │
└──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ ③ 时间窗口延迟(Pending) │
│ ───────────────────────────────────── │
│ 指标异常持续 5 分钟才真正触发通知 │
│ 瞬时抖动不产生告警 │
└──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ ④ 告警合并通知(按通知渠道合并) │
│ ───────────────────────────────────── │
│ 同一时间段内,同一服务的多条告警 │
│ 合并为一条汇总消息发送 │
└──────────────────────────────────────────┘
2 智能去重 — 窗口内合并示例
# 伪代码:基于滑动窗口的相似告警合并
class AlertDeduplicator:
def __init__(self, window_seconds=600):
self.window = window_seconds
self.buffer = {} # {fingerprint: alert_state}
def process(self, new_alert):
fp = self._fingerprint(new_alert)
if fp in self.buffer:
existing = self.buffer[fp]
# 合并计数
existing.count += 1
existing.last_seen = new_alert.timestamp
# 保持原始告警时间不变,避免重置
existing.end_time = new_alert.timestamp
return None # 不产生新告警
else:
# 新告警,添加到缓冲区
self.buffer[fp] = AlertState(
fingerprint=fp,
first_seen=new_alert.timestamp,
count=1
)
return new_alert # 产生新告警
def _fingerprint(self, alert):
"""生成告警指纹:相同指纹的告警视为同一事件"""
raw = f"{alert.metric}:{alert.host}:{alert.alert_type}"
import hashlib
return hashlib.md5(raw.encode()).hexdigest()[:16]
3 告警级别与升级策略
告警分级模型:
┌────────────────────────────────────────────────────────────┐
│ 严重程度 │ 含义 │ 响应时间 │ 通知方式 │
├────────────────────────────────────────────────────────────┤
│ P0 │ 核心业务中断 │ 立即 │ 电话+短信+IM+邮件 │
│ P1 │ 重要功能受损 │ 5分钟 │ 短信+IM+邮件 │
│ P2 │ 非核心异常 │ 30分钟 │ IM+邮件 │
│ P3 │ 提示性信息 │ 不要求 │ 邮件(可选) │
└────────────────────────────────────────────────────────────┘
自动升级机制:
原始告警 ──▶ 15分钟未处理 ──▶ 自动升级到值班主管
│
▼
30分钟未处理 ──▶ 升级到团队负责人
│
▼
60分钟未处理 ──▶ 升级到CTO/VP
告警通知触达
1 多渠道通知架构
┌────────────────┐
│ 告警事件总线 │
└───────┬────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ SMS网关 │ │ IM机器人 │ │ 语音电话 │
└──────────┘ └──────────┘ └──────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────┐
│ 统一通知模板引擎 │
│ - 短信模板 / IM模板 / 语音模板 │
│ - 上下文信息自动填充 │
└──────────────────────────────────┘
2 通知模板参考
告警通知消息内容设计,要求“一条消息看懂问题”:
[P0] 支付服务异常 - 订单量骤降
▸ 状态:FIRING (持续5分钟)
▸ 指标:http_request_total < 10 QPS
▸ 当前值:3 QPS | 正常值:1200 QPS | 偏差率:99.75%
▸ 影响范围:
- 支付接口成功率降至 32%
- 受影响用户:约 15,000 人
▸ 可能原因:
① 数据库连接池耗尽 (最近变更: v2.3.1 发布)
② 上游服务超时 (订单服务延迟 P99: 4.2s)
▸ 操作指引:
1. 查看实时大盘: http://dashboard/xxx
2. 查看日志: http://log.xxx/trace/xxx
3. 一键执行预案: RUNBOOK/payment_issue
▸ 处理人:张三 (电话: 138xxxx) | 值班经理:李四
3 值班排班系统
值班日历(轮询规则):
┌─────────┬─────────┬─────────┬─────────┬─────────┐
│ 周一 │ 周二 │ 周三 │ 周四 │ 周五 │
├─────────┼─────────┼─────────┼─────────┼─────────┤
│ 张三 │ 李四 │ 王五 │ 赵六 │ 轮流替补 │
│ (主) │ (主) │ (主) │ (主) │ (备) │
│ 钱七 │ 孙八 │ 周九 │ 吴十 │ 紧急替补 │
│ (备) │ (备) │ (备) │ (备) │ │
└─────────┴─────────┴─────────┴─────────┴─────────┘
节假日自动顺延 | 支持临时换班 | 支持个人偏好设置
案例实战:一次完整的告警处理过程
场景:数据库连接池耗尽
时间线:
14:00:00 - 某新版本发布后连接池配置错误
14:03:00 - 指标系统中"数据库活跃连接数"持续上升
14:05:00 - 告警触发:
"连接池使用率 > 90% 持续 2 分钟"
→ 级别 P1 → 通知值班人员(短信+电话+IM)
14:05:30 - 值班人员收到通知,通过手机查看告警详情
发现同时有 3 个关联服务出现类似告警
→ 系统自动聚合为同一个"事件"
14:07:00 - 值班人员点击"认领"按钮,开始处理
系统自动发送"处理中"状态给所有干系人
14:12:00 - 值班人员定位:数据库连接池 maxActive=50
新版本误改为 10,导致连接池快速耗尽
回滚配置 → 连接池恢复
14:15:00 - 指标恢复正常 → 告警自动关闭
系统发送"已恢复"通知
14:30:00 - 系统自动生成告警复盘报告
→ 同步到IM群 + 负责人邮箱
从告警到事件(Incident)的升级管理
当告警符合以下任一条件时,自动升级为事件(Incident):
| 条件 | 说明 |
|---|---|
| P0 告警 | 无论何时,立即升级 |
| P1 且 30分钟未解决 | 自动升级 |
| 连续2次错误修复尝试 | 算法检测到“修复未生效” |
| 影响到核心业务指标 | 如订单成功率 < 95% |
自愈能力与告警联动
1 策略与处理建议自动匹配
┌────────────────────┐
│ 告警触发 │
└─────────┬──────────┘
▼
┌────────────────────┐
│ 检索历史相似告警 │
│ - 是否有成功处理过? │
│ - 是否关联变更? │
└─────────┬──────────┘
▼
┌────────────────────┐
│ 从 Runbook 知识库 │
│ 匹配处理策略 │
└─────────┬──────────┘
▼
┌────────────────────┐
│ 自动执行可选动作: │
│ 1. 自动扩容 │
│ 2. 自动回滚 │
│ 3. 自动重启 │
│ (需授权策略允许) │
└────────────────────┘
2 告警自动化处置示例
# 自愈策略配置示例(YAML)
rules:
- name: "连接池耗尽自动处理"
condition:
metric: "db_connection_pool_usage"
threshold: 90
duration: "3m"
actions:
- name: "自动锁定异常SQL"
type: "kill_slow_queries"
params:
duration_threshold: "5s"
approval_required: false # 无需审批
- name: "自动扩容连接池"
type: "config_change"
params:
config_key: "maxActive"
new_value: "100"
auto_rollback: true # 5分钟后未恢复则回滚
approval_required: true # 需要审批
notifications:
- channel: "im"
template: "已自动执行应急预案,请关注"
实际执行效果:数据库类告警的自动恢复率从5%提升到35%。
告警系统的关键指标与效果
1 核心性能指标
| 指标 | 目标值 | 实际值 |
|---|---|---|
| 告警发现时间(MTTD) | ≤ 1分钟 | 45秒 |
| 告警响应时间(MTTA) | ≤ 5分钟 | 2分钟 |
| 告警恢复时间(MTTR) | ≤ 10分钟 | 5分钟 |
| 告警准确率(Precision) | ≥ 85% | 92% |
| 告警召回率(Recall) | ≥ 95% | 97% |
| 告警重复率 | ≤ 10% | 2% |
| 误报率(每周) | ≤ 5条 | 2条 |
2 降噪效果对比
实施前 vs 实施后(周平均数据对比)
告警总量: 1,200条 ──▶ 156条 ↓87%
有效告警: 220条 ──▶ 143条 ↑自动化识别率
误报/噪音: 980条 ──▶ 13条 ↓98.7%
人工介入次数: 140次 ──▶ 45次 ↓68%
3 冗余度与可靠性设计
告警系统自身的可用性保障:
┌────────────────────────────────────────────────────┐
│ 告警系统高可用方案 │
│ │
│ 采集高可用 规则引擎高可用 │
│ ┌──────────┐ ┌──────────┐ │
│ │ 双采集Agent│ │ 双实例运行 │ │
│ │ 独立进程 │ │ 主备切换 │ │
│ └──────────┘ └──────────┘ │
│ │
│ 消息队列高可用 通知通道备用计划 │
│ ┌──────────┐ ┌──────────┐ │
│ │ Kafka复制 │ │ 短信→IM→邮件 │ │
│ │ 多分区 │ │ 三级降级策略 │ │
│ └──────────┘ └──────────┘ │
└────────────────────────────────────────────────────┘
经验教训与最佳实践总结
1 踩过的坑
| 问题 | 后果 | 解决方案 |
|---|---|---|
| 告警阈值设置过于激进 | 频繁误报,团队麻木 | 采用动态基线 + 多维度检测 |
| 没有告警分组策略 | 一次故障 300+ 条告警 | 按服务/依赖关系分组聚合 |
| 通知策略单一(只有邮件) | 非工作时间无法及时响应 | 分级通知(电话/SMS/IM) |
| 缺少告警认领机制 | 多人处理同一告警/无人处理 | 增加值班排班 + 认领确认 |
| 没有告警关闭条件 | 故障已解决但告警一直挂着 | 告警自动恢复检测 |
2 最佳实践
-
告警必须有“可执行动作”
“每条告警消息必须注明下一步操作,否则不发送。” -
告警是手段,不是目的
- 能自动恢复的不告警 → 能脚本处理的不需要人
- 告警最终目标是被消除(通过自愈或根因修复)
-
持续优化闭环
- 周维度汇总告警数据 → 月维度输出优化报告
- 无效告警 → 关闭规则 + 标记降级
-
定期告警演练
- 每月一次故障注入测试(Chaos Engineering)
- 确保演练发现的问题能进入优化池
-
要包含业务上下文
不仅是技术指标,还要说明“影响了什么业务、多少用户、哪个区”。
技术栈选型参考
| 场景 | 推荐方案 | 备选方案 |
|---|---|---|
| 指标采集 | Prometheus | Telegraf |
| 存储 | Thanos + ClickHouse | VictoriaMetrics |
| 规则引擎 | 自研(基于Go) | Grafana Alerting;AlertManager |
| 通知触达 | 自研 Notify Service | PagerDuty;AlertManager webhook |
| 值班排班 | 自研 OnCall | Opsgenie;XWatch |
| 协同平台 | 自研 + 飞书/钉钉/企微 | Jira + Slack |
| 可视化 | Grafana + 自研 | Kibana + 自研 |
告警系统本质上是信息降噪系统,核心价值不是“发出更多告警”,而是 “让每一条发出的告警都值得被关注,并且尽可能自动完成处理”,从实际效果看,降噪、收敛、自愈和认领机制是告警系统能否真正落地的关键。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播