用 CloudWatch 集成 SNS 与 SQS

AWS 监控与故障排查

John Q. Martin

Principal Consultant

将 CloudWatch 警报连接到 SNS

aws cloudwatch put-metric-alarm \
  --alarm-name HighCPUUtilization \
  --metric-name CPUUtilization \
  --namespace AWS/EC2 \
  --statistic Average \
  --period 300 \
  --evaluation-periods 2 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:production-alerts \
  --ok-actions arn:aws:sns:us-east-1:123456789012:recovery-notifications

 

流程:CloudWatch 警报通过 --alarm-actions 发送到 SNS 主题,广播给订阅者——Email、SMS、Lambda 和 SQS

AWS 监控与故障排查

SNS 核心概念

组件

  • SNS 为发布/订阅:主题、发布者、订阅者
  • 主题:命名通道;发布者发送,订阅者接收
  • 一次发布,同时送达所有订阅者

订阅协议(单主题,多端点):

  • Email、SMS
  • HTTP / HTTPS
  • Lambda、SQS
  • 移动推送、Kinesis Firehose
AWS 监控与故障排查

SNS 主题类型

 

按有序性、吞吐与投递保证对比 SNS Standard 与 FIFO 主题类型

AWS 监控与故障排查

使用 AWS CLI 创建 SNS 主题

标准主题

aws sns create-topic \
  --name production-alerts

FIFO 主题

aws sns create-topic \
  --name production-alerts.fifo \
  --attributes FifoTopic=true,\
    ContentBasedDeduplication=true

启用加密

aws sns create-topic \
  --name production-alerts \
  --attributes KmsMasterKeyId=alias/aws/sns
AWS 监控与故障排查

添加 Lambda 与 SMS 订阅者

 

Lambda

aws sns subscribe \
  --topic-arn arn:aws:sns:us-east-1:123456789012:production-alerts \
  --protocol lambda \
  --notification-endpoint arn:aws:lambda:us-east-1:123456789012:function:ProcessAlert

SMS

aws sns subscribe \
  --topic-arn arn:aws:sns:us-east-1:123456789012:critical-alerts \
  --protocol sms \
  --notification-endpoint +1234567890
AWS 监控与故障排查

来自 CloudWatch 警报的 SNS 消息格式

{
  "AlarmName": "HighCPUUtilization",
  "NewStateValue": "ALARM",
  "OldStateValue": "OK",
  "NewStateReason": "Threshold Crossed: 2 datapoints [85.0, 90.0] were greater than the threshold (80.0).",
  "StateChangeTime": "2026-03-27T10:30:45.123+0000",
  "Trigger": {
    "MetricName": "CPUUtilization",
    "Namespace": "AWS/EC2",
    "Statistic": "AVERAGE",
    "Period": 300,
    "Threshold": 80.0,
    "ComparisonOperator": "GreaterThanThreshold"
  }
}
AWS 监控与故障排查

SNS 消息过滤

aws sns set-subscription-attributes \
  --subscription-arn arn:aws:sns:...:production-alerts:abc123 \
  --attribute-name FilterPolicy \
  --attribute-value '{"AlarmName":["HighCPUUtilization"],"NewStateValue":["ALARM"]}'

aws sns set-subscription-attributes \
  --subscription-arn arn:aws:sns:...:production-alerts:abc123 \
  --attribute-name FilterPolicyScope \
  --attribute-value MessageBody
AWS 监控与故障排查

用 Lambda 自定义通知格式

def lambda_handler(event, context):
    alarm = json.loads(event['Records'][0]['Sns']['Message'])

    message = f"""
ALERT: {alarm['AlarmName']}
Status: {alarm['NewStateValue']}
Reason: {alarm['NewStateReason']}
Resource: {alarm['Trigger']['Dimensions'][0]['value']}
Runbook: https://wiki.example.com/runbooks/high-cpu
    """

    sns.publish(
        TopicArn='arn:aws:sns:...:formatted-alerts',
        Subject=f"{alarm['AlarmName']}",
        Message=message
    )

 

链路:原始警报主题触发 Lambda,将其格式化为可读消息后发布到 formatted-alerts 主题供值班工程师使用,机器消费者仍订阅原始主题

AWS 监控与故障排查

结合 SQS 的扇出架构

扇出架构:一条 SNS 消息投递到多个 SQS 队列和一个 Lambda 消费者

AWS 监控与故障排查

设置扇出

四步走

  1. 创建 SQS 队列(每个消费者一个)
  2. 配置队列策略(允许 SNS 发送消息)
  3. 将队列订阅到 SNS 主题
  4. 构建消费者(拉取、处理、删除)

队列策略

{
  "Effect": "Allow",
  "Principal": { "Service": "sns.amazonaws.com" },
  "Action": "sqs:SendMessage",
  "Resource": "arn:aws:sqs:...:alarm-logging-queue",
  "Condition": {
    "ArnEquals": {
      "aws:SourceArn": "arn:aws:sns:...:production-alerts"
    }
  }
}
AWS 监控与故障排查

订阅队列

 

订阅每个队列

aws sns subscribe \
  --topic-arn arn:aws:sns:...:production-alerts \
  --protocol sqs \
  --notification-endpoint arn:aws:sqs:...:alarm-logging-queue
AWS 监控与故障排查

处理消息

消费者模式

response = sqs.receive_message(
    QueueUrl=queue_url,
    MaxNumberOfMessages=10,
    WaitTimeSeconds=20       # Long polling
)
for message in response.get('Messages', []):
    sns_msg = json.loads(message['Body'])
    alarm = json.loads(sns_msg['Message'])
    # Process alarm data
    sqs.delete_message(QueueUrl=queue_url,
                       ReceiptHandle=message['ReceiptHandle'])
AWS 监控与故障排查

带过滤与死信队列的扇出

按订阅定向投递

  • 工单队列:{"NewStateValue":["ALARM"],"Severity":["Critical"]}
  • 日志队列:无过滤(接收全部)
  • 指标队列:{"MessageType":["Metric"]}

 

死信队列(DLQ)

aws sqs set-queue-attributes \
  --queue-url https://sqs..../alarm-logging-queue \
  --attributes '{
    "RedrivePolicy": "{\"deadLetterTargetArn\":\"arn:aws:sqs:...:alarm-logging-dlq\",\"maxReceiveCount\":\"3\"}"
  }'
AWS 监控与故障排查

SNS vs. SQS:各自适用场景

对比 SNS 推送式投递与 SQS 拉取式消息队列

AWS 监控与故障排查

架构示例

 

简单告警模式:通过 SNS 发送通知到邮箱

 

异步处理模式:API 发送到 SQS 队列,由工作进程消费

多通道告警:单个警报扇出到多种通知渠道

事件管道:将源事件路由至多个 SQS 队列处理

AWS 监控与故障排查

视频小结

 

  • SNS 主题通过 Email、SMS、HTTP、Lambda 和 SQS 投递警报通知
  • 扇出模式:一条 SNS 消息 → 多个 SQS 队列并行、可靠处理
  • 消息过滤为每个订阅者降噪
  • 死信队列捕获投递失败消息
  • SNS 做推送通知,SQS 做可靠处理;二者结合实现可靠扇出
AWS 监控与故障排查

让我们一起练习吧!

AWS 监控与故障排查

Preparing Video For Download...