自动化系统告警分级:去重静默与风暴抑制实战
日报推送在凌晨被忽略的故障现场
上周我们的自动化巡检脚本在凌晨 02:15 触发了一次磁盘使用率超 95% 的异常。由于系统设计了'每天推一条日报'的汇总机制,实时异常被合并到了早上 08:00 的日报里推送到企业微信。运维同学在通勤路上划过群消息,完全没注意那行小字。等线上服务因日志写满宕机时,dmesg 里已经刷满了 blk_update_request: I/O error, dev vda, sector 123456。这证明非紧急信息不能与紧急故障共用通道,出事才推的实时通道必须独立,否则故障现场会被安静的日报彻底掩盖。
timeSensitive 与 active 的字段取舍
在重构告警模块时,我们定义了告警结构体中的两个核心布尔字段:timeSensitive 与 active。timeSensitive 标识该告警是否时间敏感(如服务进程退出、核心接口 5xx),active 标识当前是否处于激活可推送状态(受维护窗口控制)。这两个字段的取舍直接决定告警路由。
取舍逻辑必须清晰:若 active=false,即便 timeSensitive=true 也不推(如版本发布窗口);若 timeSensitive=false(如容量趋势预测),即便 active=true 也仅进入日报池。我们在华为云 FunctionGraph 中实现的判断逻辑如下,通过不同的 SMN Topic 隔离实时与离线:
def route_alert(alert):
if alert.timeSensitive and alert.active:
publish_to_smn(alert, topic='urn:smn:cn-north-4:proj:urgent')
elif alert.active:
append_to_daily_digest(alert)调用 SMN 发布接口时,若 Token 失效会收到 requests.exceptions.HTTPError: 401 Client Error,需提前刷新 AK/SK 换取的临时 Token,否则 urgent 通道会静默失败。
基于 state 的当日同类告警去重
同一天内如果 API 网关抖动,可能一小时内产生几十条'HTTP 5xx 升高'告警。我们利用华为云分布式缓存服务 DCS 的 Redis 维护一个 state 去重键:alert:{date}:{alert_type},确保同一天同类告警只推一次。
具体可复现步骤:
- 告警触发时,对 Redis 执行
SET alert:2026-11-07:api_5xx 1 NX EX 86400 - 若 Redis 返回
nil,说明当日已推过,直接丢弃或仅计数 +1 - 若返回
OK,调用 SMN 推送并附带当日累计次数
对应的 Python 片段,部署在华为云 ECS 或 FunctionGraph 均可:
import redis
r = redis.Redis(host='192.168.1.100', port=6379)
key = f'alert:2026-11-07:api_5xx'
if r.set(key, 1, nx=True, ex=86400):
print('first time, send alert')
else:
print('duplicate, skip')这保证了同一天同类告警只推一次,避免企业微信被同一条消息刷屏,也让值班同学信任每一条弹窗。
夜间静默时段的服务挂掉与库存告警
我们设定 23:00 至 07:00 为静默时段,绝大多数告警延后到早 8 点日报。但有两个例外必须穿透静默:服务进程退出(服务挂掉)与库存低于安全水位(库存告警)。在华为云 FunctionGraph 的定时器触发或 ECS 上的 cron 调度入口做小时判断:
from datetime import datetime
hour = datetime.now().hour
if 23 <= hour or hour < 7:
if not (alert.type == 'service_down' or alert.type == 'inventory_low'):
return # 静默丢弃,不调用 SMN这样夜间只推服务挂掉与库存告警,其余如'证书即将过期'自然进入次日日报,值班同学不会被无效消息叫醒,同时核心链路挂掉能第一时间收到短信。
抑制告警风暴淹没真实故障
曾经一次上游 DNS 解析失败,导致 200 个微服务实例同时报'依赖不可用',真实根因被海量告警淹没。我们在聚合层使用 Redis ZSET 实现滑动窗口限流,确保关键错误不被噪声覆盖:
- 统计 60 秒内同
root_cause标签的告警数 - 超过 50 条时,只发一条汇总告警,日志打印
Alert storm detected: 152 alerts in 60s, threshold 50 - 其余同类转入静默计数,每 10 分钟汇报一次增量
import time, redis
r = redis.Redis()
now = time.time()
r.zadd('storm:api_5xx', {str(now): now})
r.zremrangebyscore('storm:api_5xx', 0, now-60)
if r.zcard('storm:api_5xx') > 50:
send_storm_summary() # 抑制单条,推送汇总这套分级逻辑上线后,误报率大幅下降,真实故障平均发现时间从 25 分钟缩到 3 分钟,且华为云 SMN 的调用成本也降低了一半,企业微信告警群恢复了该有的严肃性。
- 点赞
- 收藏
- 关注作者
评论(0)