12

我在 Amazon SQS 中使用死信队列。我希望每当队列收到新消息时,它都应该引发 CloudWatch 警报。问题是我在 metric: of the queue 上配置了一个警报,但是在Amazon SQS Dead-Letter Queues - Amazon Simple Queue Service文档number_of_messages_sent中提到的死信队列的情况下,此指标无法按预期工作。

现在使用了一些建议,number_of_messages_visible但我不确定如何在警报中配置它。因此,如果我设置了 this 的值,metric>0那么这与在队列中获取新消息不同。如果有旧消息,则度量值将始终为>0。我可以做某种数学表达式来在某个定义的时间段内(比如说一分钟)获得这个指标的增量,但我正在寻找一些更好的解决方案。

4

7 回答 7

6

我在同样的问题上苦苦挣扎,而我的答案是改用 NumberOfMessagesSent。然后我可以为在我配置的时间段内收到的新消息设置我的标准。这是在 CloudFormation 中对我有用的方法。

请注意,如果警报因持续故障而处于警报状态,则不会发生单独的警报。您可以设置另一个警报来捕捉这些警报。即:用同样的方法,1小时内出现100个错误时报警。

更新:因为 NumberOfMessagesReceived 和 NumberOfMessagesSent 的指标取决于消息的排队方式,所以我在为 dlq 设置添加延迟后使用指标 ApproximateNumberOfMessagesDelayed 为我们的需求设计了一个新的解决方案。如果您手动将消息添加到队列中,则 NumberOfMessagesReceived 将起作用。否则在设置延迟后使用 ApproximateNumberOfMessagesDelayed。

MyDeadLetterQueue:
    Type: AWS::SQS::Queue
    Properties:
      MessageRetentionPeriod: 1209600  # 14 days
      DelaySeconds: 60 #for alarms

DLQthresholdAlarm:
 Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: "Alarm dlq messages when we have 1 or more failed messages in 10 minutes"
      Namespace: "AWS/SQS"
      MetricName: "ApproximateNumberOfMessagesDelayed"
      Dimensions:
        - Name: "QueueName"
          Value:
            Fn::GetAtt:
              - "MyDeadLetterQueue"
              - "QueueName"
      Statistic: "Sum"
      Period: 300  
      DatapointsToAlarm: 1 
      EvaluationPeriods: 2       
      Threshold: 1
      ComparisonOperator: "GreaterThanOrEqualToThreshold"
      AlarmActions:
        - !Ref MyAlarmTopic
于 2020-05-29T23:57:23.443 回答
5

我们遇到了同样的问题,并通过使用 2 个指标并创建一个数学表达式来解决它。

    ConsentQueue:
        Type: AWS::SQS::Queue
        Properties:
            QueueName: "queue"
            RedrivePolicy:
                deadLetterTargetArn:
                    Fn::GetAtt:
                        - "DLQ"
                        - "Arn"
                maxReceiveCount: 3 # after 3 tries the event will go to DLQ
             VisibilityTimeout: 65
    DLQ:
        Type: AWS::SQS::Queue
        Properties:
            QueueName: "DLQ"

    DLQAlarm:
        Type: AWS::CloudWatch::Alarm
        Properties:
            AlarmDescription: "SQS failed"
            AlarmName: "SQSAlarm"
            Metrics:
            - Expression: "m2-m1"
              Id: "e1"
              Label: "ChangeInAmountVisible"
              ReturnData: true
            - Id: "m1"
              Label: "MessagesVisibleMin"
              MetricStat:
                  Metric:
                      Dimensions:
                      - Name: QueueName
                        Value: !GetAtt DLQ.QueueName
                      MetricName: ApproximateNumberOfMessagesVisible
                      Namespace: "AWS/SQS"
                  Period: 300 # evaluate maximum over period of 5 min
                  Stat: Minimum
                  Unit: Count
              ReturnData: false
            - Id: "m2"
              Label: "MessagesVisibleMax"
              MetricStat:
                  Metric:
                      Dimensions:
                      - Name: QueueName
                        Value: !GetAtt DLQ.QueueName
                      MetricName: ApproximateNumberOfMessagesVisible
                      Namespace: "AWS/SQS"
                  Period: 300 # evaluate maximum over period of 5 min
                  Stat: Maximum
                  Unit: Count
              ReturnData: false
            ComparisonOperator: GreaterThanOrEqualToThreshold
            Threshold: 1
            DatapointsToAlarm: 1
            EvaluationPeriods: 1

周期很重要,因此最小值和最大值会在更长的周期内进行评估。 AWS 数学表达式图

于 2020-12-22T07:21:22.610 回答
4

RATE每当消息到达死信队列时,我使用度量数学函数触发警报。

ApproximateNumberOfMessagesVisible为您的ApproximateNumberOfMessagesNotVisible死信队列选择两个指标。

将度量表达式配置为RATE(m1+m2),将阈值设置为 ,0并将比较运算符选择为GreaterThanThreshold

m1+m2是给定时间队列中的消息总数。每当有新消息到达队列时,此表达式的速率将高于零。这就是它的工作原理。

于 2020-11-12T10:42:04.663 回答
3

很难实现问题中所要求的内容。如果 cloudwatch 警报的端点是发送电子邮件或通知用户 DLQ 消息到达,您可以在 SQS、SNS 和 Lambda 的帮助下做类似的事情。从 cloudwatch 中,您可以看到每当您收到任何电子邮件时 DLQ 消息如何按时增长。

  1. 为现有队列创建 SQS DLQ。
  2. 创建 SNS 主题并订阅 SNS 主题以发送电子邮件。
  3. 创建一个小型 lambda 函数,用于侦听 SQS 队列中的传入消息,如果有任何新传入消息,则将其发送到 SNS。由于 SNS 订阅了电子邮件,因此每当有新消息进入 SQS 队列时,您都会收到电子邮件。显然,lambda 函数的触发器是 SQS,批量大小是 1。
#!/usr/bin/python3
import json
import boto3
import os

def lambda_handler(event, context):
    batch_processes=[]
    for record in event['Records']:
        send_request(record["body"])


def send_request(body):
    # Create SNS client
    sns = boto3.client('sns')

    # Publish messages to the specified SNS topic
    response = sns.publish(
        TopicArn=#YOUR_TOPIC_ARN
        Message=body,    
    )

    # Print out the response
    print(response)
于 2020-05-30T07:58:59.940 回答
2

当队列条目自动流入 DLQ 时,我遇到了 Cloudwatch 警报未触发的相同问题,并且相信我已经找到了解决方案。

您需要设置:

  • 考虑一个时间段,对我来说,我设置了 5 分钟
  • 通过 SQS 集合为您需要的 dlq 添加一个指标,然后选择“ApproximateNumberOfMessagesVisible”。将统计信息设置为最大值。
  • 复制上述行,并将统计信息设置为最小值。
  • 添加一个新的空表达式 Metric ,其中详细信息为:(最大指标的 id)-(最小指标的 id)
  • 确保您只勾选并单击上面创建的新表达式的“选择指标”。

现在,这应该定期检查 DLQ 中条目数量的差异,无论它们是如何到达那里的,这样我们就可以绕过有问题的指标,如 NumberOfMessagesSent 或 NumberOfMessagesReceived。

更新:我刚刚意识到这是 Lucasz 上面提到的确切解决方案,所以认为这是它有效的确认:)

于 2021-01-21T02:11:13.913 回答
0

您可以做的是创建一个带有事件源的 lambda 作为您的 DLQ。您可以从 Lambda 将自定义指标数据发布到 CloudWatch。当您的数据满足条件时将触发警报。

使用此参考配置您的 lambda,以便在将消息发送到您的 DLQ 时触发它:Using AWS Lambda with Amazon SQS - AWS Lambda

这是一个很好的代码解释,建议我们如何将自定义指标从 Lambda 发布到 CloudWatch:使用代码示例从 Lambda 发送 CloudWatch 自定义指标

发布指标后,CloudWatch 警报将触发,因为它将与指标匹配。

于 2020-02-13T20:35:36.533 回答
0

RATE(M1+M2) 上述提到的 Terraform 工作示例

resource "aws_cloudwatch_metric_alarm" "dlq_alarm" {
  alarm_name                = "alarm_name"
  comparison_operator       = "GreaterThanThreshold"
  evaluation_periods        = "1"
  threshold                 = "0"
  alarm_description         = "desc"
  insufficient_data_actions = []
  alarm_actions = [aws_sns_topic.sns.arn]

  metric_query {
    id          = "e1"
    expression  = "RATE(m2+m1)"
    label       = "Error Rate"
    return_data = "true"
  }

  metric_query {
    id = "m1"

    metric {
      metric_name = "ApproximateNumberOfMessagesVisible"
      namespace                 = "AWS/SQS"
      period      = "60"
      stat        = "Sum"
      unit        = "Count"

      dimensions = {
        QueueName    = "${aws_sqs_queue.sqs-dlq.name}"
      }
    }
  }

  metric_query {
    id = "m2"

    metric {
      metric_name = "ApproximateNumberOfMessagesNotVisible"
      namespace                 = "AWS/SQS"
      period      = "60"
      stat        = "Sum"
      unit        = "Count"

      dimensions = {
        QueueName    = "${aws_sqs_queue.sqs-dlq.name}"
      }
    }
  }
}
于 2022-03-03T17:27:21.650 回答