3. CloudWatch指标与告警体系

CloudWatch 的指标与告警体系,本质上是一套“带坐标的时间序列 + 基于表达式的判定 + 通知路由”的组合。理解它的关键,不是记住控制台上有哪些按钮,而是搞清楚一条数据从被采集、被检索、被判定到被通知,中间经过了哪些可配置的环节。本节围绕命名空间、维度、统计周期、自定义指标、复合告警、告警抑制与通知集成七个概念展开,并给出可直接参考的配置示例。

命名空间与维度:指标的唯一坐标

CloudWatch 中每个指标由三部分唯一确定:命名空间(Namespace)、指标名(MetricName)和维度集合(Dimensions)。命名空间是顶层隔离容器,AWS 服务默认使用 AWS/EC2、AWS/RDS、AWS/Lambda 这类命名空间;自定义指标通常使用 MyApp/OrderService 这类自有命名空间。维度是键值对,例如 InstanceId=i-0abc123、Environment=prod、Service=checkout。

需要特别注意的是:维度集合是精确匹配的。同一个指标名,如果维度组合不同,就是不同的时间序列。例如 CPUUtilization 带 InstanceId 维度是一条序列,不带该维度(聚合值)又是另一条序列。因此设计维度时要有意识地规划“查询粒度”:把需要单独告警的实体(实例、队列、接口)作为维度,把仅用于筛选的属性(环境、版本)也作为维度,但不要随意增加高基数维度(如用户 ID、请求 ID),否则会导致指标数量爆炸、费用上升且难以聚合。

统计周期与统计量:同一数据的多种读法

统计周期(Period)决定数据点的时间窗口,常见取值为 60、300、900 秒。统计量(Statistic)决定在这个窗口内如何把原始样本聚合成一个值:Average、Sum、Minimum、Maximum、SampleCount,以及百分位 p50、p90、p99。选择原则与指标语义强相关:

  • CPU 使用率、内存占用率这类“比例型”指标,用 Average 更符合直觉。
  • 请求数、错误数、消息条数这类“计数型”指标,用 Sum 才有意义。
  • 延迟这类“分布型”指标,用 p99 比 Average 更能暴露长尾问题。
  • 队列积压、连接数这类“瞬时水位型”指标,用 Maximum 更能反映峰值压力。

周期与统计量必须成对考虑。一个 60 秒周期、Sum 统计的错误数,与 300 秒周期、Sum 统计的错误数,阈值含义完全不同。告警配置中如果周期选得过短,容易因单点抖动频繁触发;选得过长,则故障发现延迟增大。生产环境常用 60 秒或 300 秒作为告警评估周期。

自定义指标:把业务信号接入 CloudWatch

系统指标只能反映资源层状态,业务层的“下单失败率”“支付回调超时数”“库存扣减冲突次数”必须通过自定义指标上报。上报方式主要有两种:使用 PutMetricData API 直接写入,或通过 CloudWatch Agent / EMF(Embedded Metric Format)从日志中提取。下面是一个使用 AWS CLI 上报自定义指标的示例:

aws cloudwatch put-metric-data \
  --namespace "MyApp/OrderService" \
  --metric-name "OrderFailed" \
  --dimensions Service=checkout,Environment=prod \
  --value 1 \
  --unit Count \
  --timestamp 2025-01-15T10:00:00Z

上报时要注意三点:一是维度组合要稳定,避免同一业务含义出现多套维度;二是单位(Unit)要统一,计数用 Count、耗时用 Milliseconds、比例用 Percent;三是时间戳要准确,否则数据会落到错误的周期窗口。高频上报场景建议使用 EMF,把指标以结构化日志形式输出,由 CloudWatch Logs 自动转换为指标,减少 API 调用开销。

复合告警:用表达式组合多个条件

单一指标告警容易产生误报。例如“CPU 高于 80%”在批处理时段可能完全正常。复合告警(Composite Alarm)允许用 ALARM(...) 表达式把多个告警组合成一条规则,只有逻辑条件成立时才进入 ALARM 状态。典型写法如下:

ALARM("HighCPU") AND ALARM("HighErrorRate")
OR ALARM("QueueBacklog") AND ALARM("HighLatency")

这条规则的含义是:CPU 高且错误率高,或者队列积压且延迟高,才判定为需要通知的故障。复合告警的价值在于降噪——把多个弱信号组合成一个强信号,减少值班人员的无效响应。配置时建议先为每个基础指标建立独立告警,再用复合告警做上层聚合,这样既保留了细粒度可见性,又控制了通知量。

告警抑制与通知集成

告警抑制(Alarm Suppression)用于在已知维护窗口或上游故障期间,临时屏蔽下游告警。例如数据库主节点切换期间,应用层的连接超时告警会大量触发,此时可以抑制应用层告警,只保留数据库层告警。抑制可以通过复合告警的 NOT 逻辑实现,也可以借助 Systems Manager 的维护窗口或 EventBridge 规则在特定时间段内禁用告警动作。

通知集成方面,CloudWatch 告警通过 SNS 主题作为出口,再由 SNS 分发到邮件、短信、Lambda、SQS 或 Chatbot(Slack、Teams)。推荐做法是:按严重级别建立不同的 SNS 主题(如 critical-alerts、warning-alerts),告警动作指向对应主题,再由订阅者决定最终渠道。这样调整通知策略时只需改 SNS 订阅,不必逐个修改告警。

告警描述(AlarmDescription)中建议写清楚“这条告警代表什么业务影响、第一排查动作是什么”,例如“支付失败率超过 5%,先检查支付网关连通性与下游银行接口状态”。这比只写“错误率高”更有值班价值。
CloudWatch 指标与告警体系:从采集到通知的完整链路 数据源 AWS 服务默认指标 CloudWatch Agent PutMetricData API EMF 日志提取 指标存储与坐标 Namespace:MyApp/OrderService MetricName:OrderFailed Dimensions:Service, Env Period:60s / 300s 告警判定 Statistic:Sum / p99 Threshold:> 5 EvaluationPeriods:2 DatapointsToAlarm:2 复合告警 ALARM(A) AND ALARM(B) 降噪聚合 告警抑制 维护窗口 / 上游故障期间屏蔽 通知集成(SNS 主题路由) critical-alerts → 邮件 / 短信 / Lambda / Chatbot warning-alerts → Slack / Teams / SQS 告警状态机: OK INSUFFICIENT_DATA ALARM 判定依据:连续 EvaluationPeriods 个周期中,满足阈值的 DatapointsToAlarm 个数据点触发状态切换。

一个可参考的告警配置示例

下面以“订单服务支付失败率”为例,给出一个从自定义指标到复合告警再到通知的完整配置思路。假设业务侧每分钟上报 OrderFailed 和 OrderTotal 两个计数指标,维度为 Service=checkout, Environment=prod。

配置项 取值 说明
命名空间 MyApp/OrderService 业务自定义命名空间
指标名 OrderFailed / OrderTotal 失败数与总数分别上报
维度 Service=checkout, Environment=prod 精确匹配,避免高基数
统计周期 60 秒 兼顾灵敏度与稳定性
统计量 Sum 计数型指标必须用 Sum
失败率表达式 m1 / m2 * 100 m1=OrderFailed, m2=OrderTotal
阈值 > 5% 连续 2 个周期满足才触发
复合条件 ALARM("HighFailRate") AND ALARM("HighLatency") 失败率与延迟同时异常才通知
通知出口 SNS: critical-alerts 再分发到邮件与 Chatbot

这个示例中,失败率表达式使用了指标数学(Metric Math),它允许在告警配置中直接对多个指标做四则运算,而不必先写一个 Lambda 去计算比率。配置时要注意:参与运算的指标必须使用相同的周期,否则 CloudWatch 会按较粗的周期对齐,导致结果偏差。另外,DatapointsToAlarm 与 EvaluationPeriods 的配合决定了告警的“迟钝程度”——前者是触发所需的数据点数,后者是评估窗口长度。例如 EvaluationPeriods=3, DatapointsToAlarm=2 表示最近 3 个周期中有 2 个越界就触发,比要求 3 个全部越界更灵敏,也比只看 1 个周期更抗抖动。

不要把所有告警都指向同一个 SNS 主题。当故障发生时,一个主题可能瞬间收到几十条通知,值班人员反而无法判断优先级。按严重级别拆分主题,并在告警描述中写明业务影响,是更可靠的做法。

最后需要强调的是,告警体系不是配置完就结束的静态资产。随着业务流量模式变化、实例规格调整、依赖服务变更,原有的阈值和周期可能不再适用。建议定期回顾告警历史,统计“触发次数”与“真实故障次数”的比例,对长期只触发不产生实际影响的告警进行阈值调整或降级为看板指标,让告警真正服务于故障发现,而不是制造噪音。