Amazon SQS 死信队列 - Amazon Simple Queue Service
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Amazon SQS 死信队列

Amazon SQS 支持死信队列 (DLQ),对于无法成功处理(使用)的消息,其他队列(源队列)可以将死信队列(源队列)作为目标。死信队列对于调试应用程序或消息系统很有用,因为它们允许您隔离未使用的消息,以确定其处理不成功的原因。有关使用 Amazon SQS 控制台创建队列和为其配置死信队列的信息,请参阅配置死信队列(控制台)。调试使用者应用程序或使用者应用程序可用于使用消息后,您只需单击 Amazon SQS 控制台上的按钮,即可使用死信队列重驱动功能将消息移回源队列。

重要

Amazon SQS 不会自动创建死信队列。必须先创建队列,然后才能将其用作死信队列。

死信队列的工作方式

有时,由于各种可能的问题,例如生产者或使用者应用程序中的错误条件或导致应用程序代码出现问题的意外状态更改,无法处理消息。例如,如果用户使用某特定产品 ID 下达 Web 订单,但产品 ID 已被删除,则 Web 商店的代码会失败并显示错误,而且包含订单请求的消息将发送到死信队列。

有时,创建器和使用器可能无法解释其用于通信的协议的各个方面,从而导致消息中断或丢失。此外,消费者的硬件错误可能会损坏消息有效载荷。

redrive 策略指定了源队列死信队列以及 Amazon SQS 在何种条件下将消息从前者移动到后者(如果源队列的使用者未能处理指定次数)。maxReceiveCount是指使用者在发送到死信队列之前尝试从队列接收消息而不将其删除。将设置maxReceiveCount为较低的值(如 1)将导致无法接收消息,从而将消息移至死信队列。此类故障包括网络错误和客户端依赖关系错误。为确保您的系统能够抵御错误,请将该值设置得足够maxReceiveCount高以允许足够的重试。

redrive allow 策略指定哪些源队列可以访问死信队列。此策略适用于潜在死信队列。您可以选择是允许所有源队列、允许特定源队列还是拒绝所有源队列。默认设置是允许所有源队列使用死信队列。如果您选择允许特定队列(使用byQueue选项),则可以使用源队列亚马逊资源名称 (ARN) 指定最多 10 个源队列。如果指定denyAll,则不能将队信队列用作死信队列。

要指定死信队列,您可以使用控制台或Amazon SDK for Java。您必须为将消息发送到死信队列的每个队列执行此操作。同一类型的多个队列可将一个死信队列作为目标。有关更多信息,请参阅CreateQueueSetQueueAttributes操作的配置死信队列(控制台)RedrivePolicyRedriveAllowPolicy属性。

重要

FIFO 队列的死信队列也必须是 FIFO 队列。同样,标准队列的死信队列也必须是标准队列。

必须使用相同的队列Amazon Web Services 账户来创建死信队列和向死信队列发送消息的其他队列。此外,死信队列必须驻留在使用死信队列的其他队列所在的区域中。例如,如果您在美国东部(俄亥州)区域中创建队列,则还必须在美国东部(俄亥州)区域中死信队列。

消息的过期时间始终基于其原始入队时间戳。将消息移至死信队列时,入队时间戳保持不变。该ApproximateAgeOfOldestMessage指标表示消息何时移至死信队列,而不是消息最初发送的时间。例如,假设一条消息在移至死信队列之前在原始队列中停留了 1 天。如果死信队列的保留期为 4 天,则该消息将在 3 天后从死信队列中删除,ApproximateAgeOfOldestMessage即 3 天。因此,最佳做法是始终将死信队列的保留期设置为比原始队列的保留期长。

死信队列有哪些好处?

死信队列的主要任务是处理未消耗消息的生命周期。死信队列允许您搁置和隔离无法正确处理的消息,以确定其处理不成功的原因。设置死信队列可让您执行以下操作:

  • 为移动到死信队列的所有消息配置警报。

  • 检查日志中可能导致消息移动到死信队列的异常。

  • 分析移至死信队列的消息内容,以诊断软件或生产者或消费者的硬件问题。

  • 确定是否为使用者提供了充足的时间来处理消息。

不同的队列类型如何处理消息失败?

标准队列

标准队列会一直处理消息,直到保留期到期。这种对消息的持续处理最大限度地减少了队列被无法处理的消息阻塞的可能性。持续的消息处理还可以更快地恢复队列。

在一个处理数千条消息的系统中,拥有使用器反复无法确认和删除的大量消息可能会增加成本并给硬件带来额外负载。最好是在几次处理尝试之后将失败的消息移至死信队列,而不是在这些消息到期前一直尝试处理它们。

注意

标准队列允许大量的航班内消息。如果您的大部分消息无法使用且未发送到死信队列,则处理有效消息的速度可能会减慢。因此,为了保持队列的效率,请确保您的应用程序正确处理消息处理。

FIFO 队列

FIFO 队列通过按顺序使用来自消息组的消息来提供完全一次的处理。因此,尽管使用者可继续检索另一个消息组中的有序消息,但在阻止队列的消息得到成功处理之前,第一个消息组将保持不可用状态。

注意

FIFO 队列允许较少数量的飞行消息。因此,要防止您的 FIFO 队列被消息阻塞,请确保您的应用程序正确处理消息处理。

将消息从 FIFO 队列移至 FIFO DLQ 时,原始消息的去重 ID 将替换为原始消息的 ID。这是为了确保 DLQ 重复数据删除不会阻止存储两条恰好共享重复数据删除 ID 的独立消息。

何时应使用死信队列?

一定要在标准队列中使用死信队列。当你的应用程序不依赖于排序时,你应该始终利用死信队列。死信队列可帮助您排查不正确的消息传输操作的问题。

注意

即使您使用死信队列,也应继续监控您的队列并重试发送因临时原因而失败的消息。

一定要使用死信队列来减少消息数量并减少系统暴露于毒药消息(可以接收但无法处理的消息)的可能性。

当您希望能够无限期地继续重试传输消息时,不要在标准队列中使用死信队列。例如,如果您的程序必须等待依赖进程变为活动或可用,则不要使用死信队列。

如果您不想打破消息或操作的确切顺序,请不要在 FIFO 队列中使用死信队列。例如,不要在视频编辑套件的编辑决策列表 (EDL) 中使用带有说明的死信队列,在这种情况下,更改编辑顺序会更改后续编辑的上下文。

将消息移出死信队列

您可以使用死信队列重驱动来管理未消耗消息的生命周期。在调查了死信队列中标准未使用的消息的可用属性和相关元数据后,可以将消息重新驱动回其源队列。死信队列重启通过在移动消息时批量处理消息来降低 API 调用计费。

重启任务代表用户使用 Amazon SQS 的SendMessageBatchReceiveMessage、和DeleteMessageBatch API 来重新驱动消息。因此,所有重新驱动的消息都被视为具有新messageidenqueueTime、和保留期的新消息。死信队列重启的定价使用调用的 API 调用次数和基于 Amazon SQS 定价的账单。

默认情况下,死信队列重新驱动将消息从死信队列移动到源队列。但是,您也可以将任何其他标准队列配置为重信目的地。此外,您可以配置重启速度来设置 Amazon SQS 移动消息的速率。有关使用 Amazon SQS 控制台配置死信队列重启的说明,请参阅配置死信队列重置(控制台)

注意

Amazon SQS 控制台中的标准队列仅支持死信队列重新驱动死信队列。

Amazon SQS 不支持在将消息从死信队列中重新驱动消息时对其进行筛选和修改。

死信队列重启任务最多可以运行 36 小时。Amazon SQS 支持每个账户最多 100 个活跃重启任务。

排查死信队列的问题

在某些情况下,Amazon SQS 死信队列的行为可能并不总是符合预期。此部分概述了常见问题并说明如何解决这些问题。

使用控制台查看消息可能会导致消息移至死信队列

Amazon SQS 根据相应队列的重启策略计算在控制台中查看消息的次数。因此,如果您在控制台中查看相应队列的 redrive 策略中指定的次数的消息,则该消息将移至相应队列的死信队列。

要调整此行为,您可以执行下列操作之一:

  • 针对相应队列的重新驱动策略增大 Maximum Receives 设置。

  • 避免在控制台中查看相应队列的消息。

死信队列的 NumberOfMessagesSentNumberOfMessagesReceived 不匹配

如果您手动向死信队列发送消息,它将由 NumberOfMessagesSent 指标捕获。不过,如果因处理尝试失败而发送消息到死信队列,则此指标不会捕获该消息。因此,NumberOfMessagesSentNumberOfMessagesReceived 的值可能不同。

有关使用 Amazon SQS 控制台创建和配置死信队列重启的信息

请注意,重启死信队列需要您为 Amazon SQS 设置相应的权限,以接收来自死信队列的消息并将消息发送到目标队列。如果权限不足,则死信队列重驱到源队列不会启动消息重驱并可能使任务失败。您可以查看消息重置任务的状态以修复问题,然后重试。