2

我有一个使用 SQS 对作业进行排队的应用程序。理想情况下,我希望每项工作都能完成,但有些工作会失败。有时重新运行它们会起作用,有时它们会一直失败,直到达到保留期。. 我想尽可能长时间地将失败的作业保留在队列中,以给他们最大可能的成功机会,所以我不想设置一个maxReceiveCount. 但我确实想检测作业何时达到MessageRetentionPeriod限制,因为我需要在作业完全失败时发送警报。目前我的最长保留期为 14 天,但到那时仍有一些工作无法完成。

有没有办法检测作业何时即将到期,并从那里将其发送到死信队列以进行额外处理?

4

1 回答 1

2

在您遵循以下我的建议并假设我已经正确完成了周期的数学运算之前,如果您检查消息的频率低于每 20 分 9 秒一次,那么您最好在队列上启用重新驱动策略

SQS 的“重新驱动策略”允许您在接收到阈值数量后将消息迁移到死信队列。AWS 允许的最大接收数为 1000,超过 14 天,每次接收大约需要 20 分钟。(为简单起见,假设您的工作不会错过读取队列消息的尝试。您可以调整数字以建立对失败的容忍度。)

如果您检查的频率高于此,您将需要实施以下解决方案。


您可以在处理消息时检查此“截止日期”(当作业即将到期时),如果消息已超过您放弃它们的时间,则将消息发送到死信队列。

添加到当前例程的伪代码:

  • 调用GetQueueAttributes以获取队列的消息保留期的计数(以秒为单位)。
  • 调用ReceiveMessage将消息从队列中拉出。确保明确请求 SentTimestamp 可见。
  • Foreach 消息,
    • 通过将邮件保留期添加到发送的时间戳来查找邮件的到期时间。
    • 通过从消息的到期时间中减去您想要的时间量来创建您的截止日期。
    • 将截止日期与当前时间进行比较。如果截止日期已过:
      • 调用SendMessage将您的消息发送到死信队列。
      • 调用DeleteMessage从您正在处理的队列中删除您的消息。
    • 如果截止日期尚未过去:
      • 正常处理作业。

这是 Powershell 中的示例实现:

$queueUrl = "https://sqs.amazonaws.com/0000/my-queue"
$deadLetterQueueUrl = "https://sqs.amazonaws.com/0000/deadletter"

# Get the message retention period in seconds
$messageRetentionPeriod = (Get-SQSQueueAttribute -AttributeNames "MessageRetentionPeriod" -QueueUrl $queueUrl).Attributes.MessageRetentionPeriod

# Receive messages from our queue.  
$queueMessages = @(receive-sqsmessage -QueueUrl $queueUrl -WaitTimeSeconds 5 -AttributeNames SentTimestamp)

foreach($message in $queueMessages)
{
    # The sent timestamp is in epoch time.
    $sentTimestampUnix = $message.Attributes.SentTimestamp

    # For powershell, we need to do some quick conversion to get a DateTime.
    $sentTimestamp = ([datetime]'1970-01-01 00:00:00').AddMilliseconds($sentTimestampUnix)

    # Get the expiration time by adding the retention period to the sent time.
    $expirationTime = $sentTimestamp.AddDays($messageRetentionPeriod / 86400 )

    # I want my cutoff date to be one hour before the expiration time.
    $cutoffDate = $expirationTime.AddHours(-1)

    # Check if the cutoff date has passed.
    if((Get-Date) -ge $cutoffDate)
    {
        # Cutoff Date has passed, move to deadletter queue

        Send-SQSMessage -QueueUrl $deadLetterQueueUrl -MessageBody $message.Body

        remove-sqsmessage -QueueUrl $queueUrl -ReceiptHandle $message.ReceiptHandle -Force
    }
    else
    {
        # Cutoff Date has not passed. Retry job?
    }
}

这将为您处理的每条消息增加一些开销。这还假设您的消息处理程序将在截止时间和到期时间之间接收消息。确保您的应用程序经常轮询以接收消息。

于 2015-02-04T03:33:07.713 回答