掌握 AWS CloudWatch,实现主动性能监控与优化

通过掌握 CloudWatch,解锁 AWS 的峰值性能。学习设置自定义指标、利用百分位统计(P99/P95)进行精确延迟跟踪,并配置智能告警以触发自动扩展。本指南提供可操作步骤,帮助构建优化的监控仪表板,并在性能瓶颈影响最终用户之前主动解决它们。

掌握 AWS CloudWatch,实现主动性能监控与优化

AWS CloudWatch 是许多 AWS 事件变得可理解的起点。缓慢的结账流程、突然受限的 Lambda 函数、连接耗尽的 RDS 数据库或不断增长的 SQS 队列,都会在指标和日志中留下线索。难点不在于开启 CloudWatch,而在于选择能帮助你在用户告知问题之前采取行动的信号。

良好的 CloudWatch 监控将平台症状与应用程序行为联系起来。CPU、内存和 I/O 很重要,但结账失败、队列年龄、支付延迟以及每分钟成功作业数量也同样重要。

AWS CloudWatch 的核心组件

CloudWatch 基于收集时间序列数据的系统运行,这些数据被称为指标,然后通过告警根据阈值进行评估。这些数据通过仪表板可视化,并由日志事件补充。

1. 指标:监控的基础

指标是随时间跟踪的数值测量值。每个 AWS 服务都会自动发布标准指标(例如,EC2 CPU 利用率、S3 请求计数)。然而,真正的性能监控需要超越默认设置。

标准指标与自定义指标

  • 标准指标: 由 AWS 服务自动收集。分辨率因服务和配置而异;许多常见服务发布 1 分钟指标,而一些基本或较旧的配置使用 5 分钟周期。
  • 自定义指标: 您自行发布的数据,通常用于衡量特定于应用程序的性能指标。

使用 AWS CLI 发布自定义指标:

您可以使用 put-metric-data 命令发布自定义指标。这对于监控应用程序响应时间、队列深度或关键业务运营状态至关重要。

aws cloudwatch put-metric-data \
    --metric-name "CheckoutLatency" \
    --namespace "MyApp/ECommerce" \
    --value 150 \
    --unit "Milliseconds" \
    --region us-east-1

指标粒度

CloudWatch 自定义指标可以是标准分辨率或高分辨率。高分辨率自定义指标可以以 1 秒分辨率存储,并在更短周期内触发告警,这对快速变化的系统很有用。请有选择地使用,因为更高的数量和更多的告警可能会增加成本。

2. 告警:基于阈值触发操作

告警在三种状态之间转换:OKINSUFFICIENT_DATAALARM。当指定阈值在定义的周期数内被违反时,告警会触发操作。

设置性能告警

有效的性能告警侧重于领先指标,而不仅仅是反应性故障。例如,监控 EC2 CPU 利用率很好,但监控 T 系列实例的 BurstBalance 指标可以在利用率达到 100% 之前预测未来的限制。

示例:设置高延迟告警

如果您的自定义 CheckoutLatency 指标在连续三个 1 分钟周期内平均值超过 500 毫秒,则触发告警并通知 SNS 主题。

aws cloudwatch put-metric-alarm \
    --alarm-name "HighCheckoutLatencyAlarm" \
    --alarm-description "Alert when P95 latency exceeds 500ms" \
    --metric-name "CheckoutLatency" \
    --namespace "MyApp/ECommerce" \
    --statistic Average \
    --period 60 \
    --threshold 500 \
    --evaluation-periods 3 \
    --datapoints-to-alarm 3 \
    --comparison-operator GreaterThanThreshold \
    --actions-enabled \
    --alarm-actions arn:aws:sns:us-east-1:123456789012:PerformanceAlertsTopic

最佳实践:利用百分位数(p99, p95) 监控延迟时,避免仅依赖 Average。一小部分但令人痛苦的慢速请求可能会隐藏在看似健康的平均值中。当尾部延迟很重要时,请使用 P99P95 等统计信息。

3. 仪表板:可视化系统健康状态

仪表板将相关指标整合到一个单一的视图中。有效的仪表板针对受众(例如,运营、开发、高管)量身定制。

构建性能优化仪表板

一个结构良好的性能优化仪表板应该对相关指标进行分组。

  • 系统健康面板: CPU 利用率、网络输入/输出、磁盘读/写 IOPS(适用于 EC2/EBS)。
  • 应用程序性能面板: 自定义延迟指标(P99)、错误率(HTTP 5xx 计数)、请求吞吐量。
  • 成本/效率面板: 运行实例数、预留实例利用率、EBS 卷利用率(用于识别未充分利用的存储)。

CloudWatch 仪表板支持复杂的小部件,包括文本注释、指标数学表达式(例如,计算效率比率),甚至嵌入 CloudWatch Logs Insights 查询结果。

CloudWatch 用于自动化性能优化

监控数据只有在驱动行动时才有价值。CloudWatch 告警是启动自动化优化工作流程的主要机制。

将告警与自动扩展集成

最强大的优化技术之一是使用 CloudWatch 告警驱动 AWS 自动扩展组(ASG)。这确保了容量精确匹配需求,防止过度配置(节省成本)和配置不足(性能下降)。

示例:基于队列深度扩展

不要仅依赖 CPU,而是根据等待处理的后备工作负载进行扩展。对于 SQS 队列,您可以在 ApproximateNumberOfMessagesVisible 指标上创建告警。当告警进入 ALARM 状态时,它会触发自动扩展操作,向 ASG 添加一个 EC2 实例。

配置提示: 确保您的扩展策略使用目标跟踪扩展,配置为维持平均利用率指标(例如,保持平均 CPU 为 60%)。这允许 AWS 动态管理扩展,通常优于静态步进扩展。

利用日志进行深入分析

当性能问题发生时,CloudWatch Logs 对于根本原因分析至关重要。

  • 集中式日志记录: 配置所有应用程序和服务(VPC 流日志、Lambda 日志、ECS/EKS 容器日志)以流式传输到 CloudWatch Logs。
  • Log Insights: 使用 Log Insights 中强大的查询语言快速搜索大量日志。例如,查找所有耗时超过 2 秒的请求:
fields @timestamp, @message
| filter @message like /duration: \d{4,}/ 
| parse @message "*duration: *ms*" as duration
| filter as_number(duration) > 2000
| sort @timestamp desc
| limit 50

CloudWatch 监控的最佳实践

为了最大化从 CloudWatch 获得的价值并优化性能:

  1. 监控服务限制: 在您的 AWS 服务配额上设置告警(例如,最大运行 Lambda 并发执行数、您的账户可用的最大 EBS IOPS)。达到配额会完全停止性能,通常没有明确的应用程序错误。
  2. 建立性能基线: 在优化之前,监控系统在高峰和非高峰时段的表现,以定义正常状态。这可以防止基于无关噪声设置告警。
  3. 使用指标数学计算比率: 直接在 CloudWatch 中计算效率比率。例如,(总错误数 / 总请求数) * 100 以获得失败率的直接百分比,而不是处理多个单独的指标。
  4. 成本管理: 自定义的高分辨率指标成本更高。请谨慎使用。仅对关键、快速变化的系统(如负载均衡器)使用 1 分钟分辨率。默认的 5 分钟分辨率对于大多数后端服务来说已经足够。
  5. 标记策略: 确保所有受监控的资源(EC2、RDS、Lambda)都有一致的标记。这允许您创建特定于环境的过滤仪表板和告警(例如,Env: ProdApp: CheckoutService)。

让仪表板匹配事件

CloudWatch 仪表板应该帮助某人在压力下做出决策。如果仪表板只证明系统有很多指标,那么在中断期间它不会有帮助。

对于 Web 应用程序,我喜欢将第一个屏幕围绕一个简单的路径构建:流量进入,应用程序处理它,依赖项响应,用户要么成功要么失败。这通常意味着这些小部件彼此靠近:

  • 来自负载均衡器或 API Gateway 的请求计数和错误计数。
  • 同一入口点的 P95 或 P99 延迟。
  • 应用程序级别的成功和失败指标。
  • ECS、EKS、Lambda 或 EC2 的 CPU、内存和任务计数。
  • RDS、DynamoDB、Redis、SQS 或外部依赖项指标,这些指标通常可以解释慢速请求。

确切的服务会变化,但形状保持不变。如果结账延迟飙升,您希望看到流量是否激增、错误是否增加、数据库延迟是否攀升或工作者是否落后。将这些线索放在一个地方。

避免混合生产、暂存和开发环境而没有明确标签的仪表板。在事件期间,最终会有人读错图表。使用维度、标签和命名约定使环境显而易见。

谨慎使用百分位数

百分位数对于延迟很有用,因为平均值会隐藏糟糕的用户体验。如果大多数请求在 100 毫秒内完成,但一小部分需要 8 秒,平均值可能看起来仍然可以接受。百分位数图使长尾可见。

也就是说,百分位数不是魔法。它们需要足够的流量才能有意义,并且在低流量服务上可能看起来很嘈杂。对于每小时运行几次的小型内部作业,最大持续时间或明确的失败指标可能比 P99 更有用。对于具有稳定流量的公共 API,P95 和 P99 通常值得关注。

当您创建告警时,请确保 CLI 命令使用您实际想要的统计信息。对于百分位数告警,请使用 --extended-statistic p95p99,而不是 --statistic Average

aws cloudwatch put-metric-alarm \
  --alarm-name "HighCheckoutP95Latency" \
  --metric-name "CheckoutLatency" \
  --namespace "MyApp/ECommerce" \
  --extended-statistic p95 \
  --period 60 \
  --threshold 500 \
  --evaluation-periods 5 \
  --datapoints-to-alarm 3 \
  --comparison-operator GreaterThanThreshold \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:PerformanceAlertsTopic

datapoints-to-alarm 设置很重要。要求五个周期中的三个可以捕捉持续的问题,而不会因为一个嘈杂的分钟而分页。对于关键系统,根据实际历史流量进行调整,而不是猜测。

将应用程序指标放在 AWS 指标旁边

AWS 服务指标告诉您平台看到了什么。您的应用程序指标告诉您用户正在尝试做什么。您两者都需要。

例如,ECS 服务可能显示正常的 CPU 和内存,而结账功能因支付提供商超时而中断。CloudWatch 不会知道这一点,除非您的应用程序发布诸如 PaymentAuthorizationFailureCheckoutCompletedPaymentProviderLatency 之类的指标。

良好的自定义指标通常与业务操作相关联:

  • LoginSucceededLoginFailed
  • OrderCreated
  • PaymentAuthorizationLatency
  • QueueJobProcessed
  • ImportRowsFailed

保持维度有用但不过度。ServiceEnvironmentRegion 通常没问题。为每个用户 ID、请求 ID 或 URL 路径设置一个维度可能会产生高基数成本,并使数据更难使用。对于详细的按请求调查,日志和跟踪是更好的地方。

当您已经编写结构化 JSON 日志时,CloudWatch Embedded Metric Format 很方便。它允许您从同一事件发出日志和指标,这使应用程序检测更简单。权衡是成本和数量:结构化日志很强大,但嘈杂的日志会很快变得昂贵。

围绕症状和原因构建告警

一个常见的监控错误是仅对原因设置告警:CPU 高、内存高、磁盘队列高。这些很有用,但它们并不总是意味着用户受到影响。另一个错误是仅对症状设置告警:错误率高、延迟高、订单失败。这些告诉您用户受到影响,但它们不解释原因。

一个实用的设置同时使用两者:

  • 症状告警通知服务所有者:错误率高、延迟高、无成功订单、队列年龄增加。
  • 原因告警支持诊断:数据库 CPU、受限的 DynamoDB 请求、Lambda 并发、耗尽突发余额、磁盘空间低。
  • 容量告警提前警告:自动扩展接近最大值、服务配额接近、队列积压增长速度快于工作者处理速度。

如果每个告警都以相同的紧急程度通知同一个渠道,人们就会不再信任该渠道。使警告告警可见而不唤醒某人,并为用户影响或几乎确定的用户影响保留分页。

使用 Logs Insights 回答问题,而不仅仅是搜索

CloudWatch Logs Insights 在团队保存他们反复提出的问题的查询时最有用。示例:

fields @timestamp, status, path, durationMs
| filter status >= 500
| stats count() as errors by path
| sort errors desc
| limit 20
fields @timestamp, requestId, customerId, durationMs
| filter durationMs > 2000
| sort durationMs desc
| limit 50
fields @timestamp, @message
| filter @message like /ThrottlingException|Rate exceeded/
| sort @timestamp desc
| limit 100

这些查询不能替代跟踪,但它们对于第一响应来说足够快。将它们保存在运行手册或仪表板文本小部件中,这样下一个人就不必在系统缓慢时记住语法。

在提高可见性的同时审查成本

当团队开启高分辨率自定义指标、永久保留所有日志或创建太多独特的指标维度时,CloudWatch 可能会变得昂贵。性能监控不应产生意外的账单。

有意设置保留期。生产应用程序日志可能需要比开发中的调试日志更长的保留期。安全和审计日志可能有自己的规则。对于冗长的服务,考虑在日志到达 CloudWatch 之前过滤或采样嘈杂的信息性日志。

对于指标,从与您可以采取的行动相匹配的分辨率开始。如果服务需要几分钟才能安全扩展,一秒指标可能不会改善响应。如果必须立即捕获延迟峰值,高分辨率指标对于那个狭窄的信号可能是值得的。

一个有用的初始 CloudWatch 设置

对于新的生产服务,一个可靠的初步设置是:

  1. 一个包含流量、延迟、错误、饱和度和依赖项健康状态的仪表板。
  2. 针对高错误率、高延迟、预期流量时无成功流量、队列年龄和低磁盘空间(如适用)的告警。
  3. 针对主要用户操作的应用程序指标。
  4. 带有请求 ID 和足够字段的结构化日志,以便按路由、状态、持续时间和依赖项进行过滤。
  5. 针对慢速请求、5xx 错误、限制和失败后台作业的已保存 Logs Insights 查询。
  6. 每月审查嘈杂的告警、缺失的告警和 CloudWatch 成本。

当 CloudWatch 成为团队运作方式的一部分,而不仅仅是用户在抱怨后才打开的仪表板时,它才能发挥最佳效果。从您在事件期间提出的问题开始,然后围绕这些问题塑造指标、告警和日志。