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

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

Amazon SNS 死信队列 (DLQ)

死信队列是 Amazon SNS 订阅针对无法成功传输给订阅者的消息可以将其视为目标的一个 Amazon SQS 队列。由于客户端错误或服务器错误而无法传输的消息将保留在死信队列中,以进行进一步分析或重新处理。有关更多信息,请参阅 为订阅配置 Amazon SNS 死信队列Amazon SNS 消息传输重试

注意
  • 亚马逊 SNS 订阅和亚马逊 SQS 队列必须位于 Amazon 相同的账户和区域下。

  • 对于 FIFO 主题,您可以将 Amazon SQS 队列用作 Amazon SNS 订阅的死信队列。FIFO 主题订阅使用 FIFO 队列,而标准主题订阅使用标准队列。

  • 要将加密的 Amazon SQS 队列用作死信队列,您必须使用自定义 KMS,其密钥策略允许亚马逊 SNS 服务委托人访问 API 操作。 Amazon KMS 有关更多信息,请参阅本指南中的 静态加密 以及 Amazon Simple Queue Service 开发人员指南中的使用服务器端加密 (SSE) 和 Amazon KMS保护 Amazon SQS 数据

为什么消息传输会失败?

通常,当 Amazon SNS 由于客户端服务器端错误无法访问订阅的终端节点时,消息传输将失败。当 Amazon SNS 收到客户端错误,或者继续收到超出相应重试策略指定的重试次数的消息的服务器端错误时,Amazon SNS 会丢弃该消息——除非已将死信队列附加到订阅。失败的传输不会更改您的订阅状态。有关更多信息,请参阅 Amazon SNS 消息传输重试

客户端错误

当 Amazon SNS 具有过时的订阅元数据时,可能会发生客户端错误。当拥有者删除终端节点(例如,订阅了 Amazon SNS 主题的 Lambda 函数)时,或当拥有者更改附加到已订阅终端节点的策略的方式致使 Amazon SNS 无法将消息传输到终端节点时,通常会发生这些错误。Amazon SNS 不会重试因客户端错误导致失败的消息传输。

服务器端错误

当负责已订阅终端节点的系统变得不可用或返回一个指示该系统无法处理来自 Amazon SNS 的有效请求的异常时,可能会发生服务器端错误。在发生服务器端错误时,Amazon SNS 会使用线性或指数回退函数重试失败的传输。对于由亚马逊 SQS Amazon Lambda支持的 Amazon 托管终端节点导致的服务器端错误,Amazon SNS 在 23 天内重试交付最多 100,015 次。

客户托管的终端节点(如 HTTP、SMTP、SMS 或移动推送)也可能会导致出现服务器端错误。Amazon SNS 也将重试传输到这些类型的终端节点。虽然 HTTP 终端节点支持客户定义的重试策略,但 Amazon SNS 会将 SMTP、SMS 和移动推送终端节点的内部传输重试策略设置为 50 次(时间超过 6 小时)。

死信队列的工作方式

死信队列将附加到 Amazon SNS 订阅(而不是主题),因为消息传输是在订阅级别进行的。这使您能够更轻松地识别每条消息的原始目标终端节点。

与 Amazon SNS 订阅关联的死信队列是普通 Amazon SQS 队列。有关消息保留期的更多信息,请参阅 Amazon Simple Queue Service 开发人员指南与消息相关的配额。您可以使用 Amazon SQS SetQueueAttributes API 操作来更改消息保留策略。为了使您的应用程序更具弹性,我们建议将死信队列的最长保留期设置为 14 天。

如何将消息移至死信队列中?

可以使用重新驱动策略 将您的消息移至死信队列中。重新驱动策略是一个引用死信队列 ARN 的 JSON 对象。deadLetterTargetArn 属性指定 ARN。ARN 必须指向与您的亚马逊 SNS 订阅位于 Amazon Web Services 账户 相同和区域的亚马逊 SQS 队列。有关更多信息,请参阅 为订阅配置 Amazon SNS 死信队列

以下 JSON 对象是附加到 SNS 订阅的示例重新驱动策略。

{ "deadLetterTargetArn": "arn:aws:sqs:us-east-2:123456789012:MyDeadLetterQueue" }

如何将消息移出死信队列?

可以通过两种方式将消息移出死信队列:

  • 避免编写 Amazon SQS 使用者逻辑 – 将死信队列设置为 Lambda 函数的事件源以耗尽死信队列。

  • 编写 Amazon SQS 使用者逻辑 — 使用 Amazon SQS API Amazon 、SDK Amazon CLI 或编写自定义使用者逻辑,用于轮询、处理和删除死信队列中的消息。

如何监控和记录死信队列?

您可以使用亚马逊 CloudWatch 指标来监控与您的 Amazon SNS 订阅相关的死信队列。所有 Amazon SQS 队列每隔一分钟发布一次 CloudWatch 指标。有关更多信息,请参阅《亚马逊简单队列服务开发者指南》中的 Amazon SQS 可用 CloudWatch 指标。所有带有死信队列的 Amazon SNS 订阅也会发布指标。 CloudWatch 有关更多信息,请参阅 使用监控亚马逊 SNS 主题 CloudWatch

要收到死信队列中的活动通知,您可以使用 CloudWatch 指标和警报。为该NumberOfMessagesSent指标设置警报是不合适的,因为该指标不会捕获因处理尝试失败而发送到 DLQ 的消息。取而代之的是使用该NumberOfMessagesReceived指标,它会捕获 DLQ 收到的所有消息,包括因处理失败而移动的消息。

CloudWatch 警报设置示例
  1. 为该NumberOfMessagesReceived指标创建CloudWatch警报

  2. 将警报阈值设置为 1(或基于您的期望值和 DLQ 流量的另一个适当值)。

  3. 指定警报响起时要通知的 Amazon SNS 主题。此 Amazon SNS 主题可以将告警通知传输到任何终端节点类型(例如,电子邮件地址、电话号码或移动寻呼机应用程序)。

您可以使用 CloudWatch 日志来调查导致任何 Amazon SNS 交付失败的异常,以及将消息发送到死信队列。Amazon SNS 可以记录成功和失败的交付。 CloudWatch有关更多信息,请参阅 移动应用程序属性