我有一个应用程序,它使用SQS对作业进行排队。理想情况下,我希望每一份工作都能完成,但有些工作会失败。有时重新运行它们会起作用,有时它们会一直失败,直到达到保留期。我希望尽可能长时间地将失败的作业保留在队列中,以给它们最大可能成功的机会,所以我不想设置maxReceiveCount
。但我确实想检测作业何时达到MessageRetentionPeriod
限制,因为当作业完全失败时,我需要发送警报。目前,我的最大保留期为14天,但有些工作到那时还无法完成。
有没有一种方法可以检测作业何时即将过期,并从那里将其发送到死信队列进行额外处理?
在遵循我下面的建议并假设我正确计算了时段之前,如果您检查消息的频率低于每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?
}
}
这将给您处理的每条消息增加一些开销。这还假设您的消息处理程序将在截止时间和过期时间之间接收消息。请确保您的应用程序轮询的频率足以接收消息。