做监控的团队大多经历过类似的路径:先把能监控的都接进来——CPU、内存、磁盘、链路、服务状态、日志、备份……平台上有了数据、有了状态、有异常提示,感觉"监控终于跑起来了"。
但再往后跑一段时间,会出现一种很别扭的状态:
- 群消息越来越多
- 平台红点越来越密
- 值班的人一直在处理"异常"
- 明明什么都监控到了,团队却还在被动救火
问题很多时候不在"监控做得不够全",而在于告警停在了"发出来"这一步,没有继续往下做——把告警变成真正可处理的事件。
真正让人变累的,不是告警数量
第一反应会说"告警太多了",但更准确的说法是:不同类型、不同优先级的问题,全都混在一起砸向值班人员。
- CPU高是一条告警,门店断网是一条告警,备份失败也是一条告警
- 从平台看都叫"异常",但从处理优先级看根本不是一回事
- 值班的人每次看到告警,第一步不是处理,而是先判断"这条到底重不重要"
还有一种更耗人的:一个故障带出一串告警。
比如一条线路抖动,后面连着出来:设备离线、链路异常、服务不可达、接口超时、业务访问失败……如果没有做归并,值班看到的不是"一个故障",而是五六条都像要立刻处理的消息。
时间一久,最先被消耗掉的不是执行力,而是判断力。
最容易把团队拖进"假忙"的4类告警
1. 重复告警
同一个问题短时间反复触发。平台看着很热闹,处理价值很低。
2. 连锁告警
一个根因故障带出大量下游异常。不做归并就会一直盯着表象跑。
3. 短时抖动告警
波动值得观察,但不值得立刻打断人。最容易制造疲劳,也最容易让人对提醒失去敏感。
4. 信息价值低的告警
只告诉你"有异常",但:这是哪台设备?属于哪个门店?负责人是谁?最近有没有类似历史?影响范围多大?——都得自己再查。
平台只完成了"发现问题",真正的处理成本还是留给了人。
告警治理最小闭环:分级 → 去重 → 归并 → 路由 → 升级 → 复盘

看起来不复杂,但很多团队做到"发现异常"就停了。真正拉开效率差距的,是后面这条链路有没有打通。
举个场景
某门店出口网络抖动3分钟。
没有治理时,值班群里收到:
- 门店出口链路异常
- 网络设备离线
- VPN连接中断
- 收银服务不可达
- 监控视频上报失败
- 远程运维通道异常
看起来6个问题。
做了归并和分级后,值班侧收到:
主告警:某门店网络中断
- 影响范围:收银、远程运维、视频回传
- 责任对象:网络组
- 持续时间:3分钟
- 是否需要升级:是
- 是否需要派单:是
两种体验差别非常大。前者是在"看消息",后者才是在"处理故障"。
先从3个动作开始落地
不需要一上来重做平台、重配规则。先从这3步开始:
1. 把告警分成4级,不是所有告警都进同一个通道
| 级别 | 定义 | 处理方式 |
|---|---|---|
| P1 | 核心业务中断、主链路中断 | 立即处理,电话通知 |
| P2 | 重要设备异常、冗余切换、备份失败 | 尽快处理,工单派发 |
| P3 | 磁盘使用率高、普通设备离线 | 工作时间处理 |
| P4 | 趋势波动、短时抖动、低风险异常 | 汇总观察,不实时通知 |
这一步最重要的不是分得多精细,而是先把"必须立刻打扰人"和"可以先不打扰人"拆开。
如果你用的是阿里云CMS(云监控),可以通过报警规则的"报警级别"字段做分级,再配合事件总线EventBridge按级别路由到不同通知渠道(P1走电话、P2走钉钉工单、P3/P4走消息汇总)。
2. 做一条最基础的去重规则
同一资产 + 同一监控项 + 同一异常类型 + 10分钟内重复触发 = 合并为1条
同一台交换机、同一条链路状态异常、10分钟内触发5次——值班侧应该看到1条,不是5条。
去重规则的伪代码逻辑:
def should_suppress(new_alert, active_alerts, window_minutes=10):
"""
去重判断:同一聚合键在窗口期内已有活跃告警则抑制
"""
agg_key = f"{new_alert['asset_id']}:{new_alert['metric']}:{new_alert['alert_type']}"
for active in active_alerts:
if active['agg_key'] == agg_key:
elapsed = (new_alert['timestamp'] - active['first_triggered']).total_seconds()
if elapsed <= window_minutes * 60:
# 合并到已有告警,追加计数
active['count'] += 1
active['last_triggered'] = new_alert['timestamp']
return True # 抑制,不重复通知
return False # 新事件,正常通知
3. 规定"主告警"最少带什么信息
归并不是折叠就结束了。主告警至少要带:
- 异常对象
- 影响范围
- 优先级
- 持续时间
- 责任人/责任组
- 是否需要升级
- 是否需要派单
做到这一步,值班看到的就不再是"又出事了",而是"这件事是谁的、影响多大、要不要马上接"。
怎么判断告警治理有没有见效
先看4个数:
- 每天总告警量有没有下降
- 重复告警占比有没有下降
- 夜间打断次数有没有下降
- 从告警出现到责任人接手的时间有没有缩短
如果4个数都没变化,大概率不是平台不够强,而是分级、去重、归并还没有真正落到值班侧。
参考效果(120+门店项目数据)
| 指标 | 治理前 | 治理后 | 变化 |
|---|---|---|---|
| 日均告警条数 | 2000-3000 | 60-100条事件 | ↓97% |
| 值班翻看告警时间 | 40-60分钟/天 | 10-15分钟/天 | ↓75% |
| P1告警被淹没概率 | ~12% | <1% | 基本消除 |
| 夜间无效打断次数 | 8-12次/晚 | 1-2次/晚 | ↓85% |
这组数据不是一天做到的,从分级开始做起,第一周就能明显感觉到值班侧"安静了"。
小结
告警体系从"做全"到"做准",是运维体系成熟度提升的关键一步。核心不是再多加规则,而是把后面的链路打通:分级让人知道轻重、去重让人不重复劳动、归并让人看到故障而非看到消息、路由让对的人接到对的事。
不需要上很重的AIOps,在现有监控系统上调配置、调流程就能显著改善。建议先从分级和去重开始,一周内就能看到值班侧的体感变化。
附:钉钉机器人告警通知模板(可直接用)
分级做完之后,不同级别走不同通知渠道。P1/P2走钉钉机器人独立推送给值班人,P3/P4走汇总群消息。以下是钉钉Webhook的P1告警通知格式:
import requests
import json
def send_dingtalk_alert(webhook_url: str, alert: dict):
"""
P1告警发送钉钉机器人通知(Markdown格式)
"""
severity_emoji = {
"P1": "🔴", "P2": "🟠", "P3": "🟡", "P4": "⚪"}
markdown_text = f"""### {severity_emoji.get(alert['severity'], '')} {alert['severity']} 告警:{alert['title']}
**影响范围**:{alert['impact']}
**异常对象**:{alert['asset']}({alert['site_name']})
**持续时间**:{alert['duration']}
**责任组**:{alert['team']}
**建议动作**:{alert['suggested_action']}
---
> 请值班工程师5分钟内确认处理"""
payload = {
"msgtype": "markdown",
"markdown": {
"title": f"[{alert['severity']}] {alert['title']}",
"text": markdown_text
},
"at": {
"atMobiles": [alert['oncall_phone']],
"isAtAll": alert['severity'] == 'P1'
}
}
resp = requests.post(webhook_url, json=payload, timeout=5)
return resp.status_code == 200
把这段嵌入你的告警路由逻辑,归并后的主事件按分级自动推送到对应钉钉群/个人,值班的人收到的就是"可直接处理"的信息,不是"需要先判断"的噪音。