

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

# Amazon SNS 死信队列
<a name="sns-dead-letter-queues"></a>

死信队列是一个 Amazon SQS 队列，Amazon SNS 订阅可以将其视为目标，用于存放无法成功传输给订阅用户的消息。由于客户端错误或服务器错误而无法传输的消息将保留在死信队列中，以进行进一步分析或重新处理。有关更多信息，请参阅[为订阅配置 Amazon SNS 死信队列](sns-configure-dead-letter-queue.md)和[Amazon SNS 消息传输重试](sns-message-delivery-retries.md)。

**注意**  
亚马逊 SNS 订阅和亚马逊 SQS 队列必须位于 AWS 相同的账户和区域下。
对于 [FIFO 主题](sns-fifo-topics.md)，您可以将 Amazon SQS 队列用作 Amazon SNS 订阅的死信队列。FIFO 主题订阅使用 FIFO 队列，而标准主题订阅使用标准队列。
要将加密的 Amazon SQS 队列用作死信队列，您必须使用自定义 KMS，其密钥策略允许亚马逊 SNS 服务委托人访问 API 操作。 AWS KMS 有关更多信息，请参阅本指南中的 [使用服务器端加密保护 Amazon SNS 数据安全](sns-server-side-encryption.md) 以及 *Amazon Simple Queue Service 开发人员指南*中的[使用服务器端加密 (SSE) 和 AWS KMS保护 Amazon SQS 数据](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-server-side-encryption.html)。

## 为什么消息传输会失败？
<a name="why-do-message-deliveries-fail"></a>

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

### 客户端错误
<a name="client-side-errors"></a>

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

### 服务器端错误
<a name="server-side-errors"></a>

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

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

## 死信队列的工作方式
<a name="how-do-dead-letter-queues-work"></a>

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

与 Amazon SNS 订阅关联的死信队列是普通 Amazon SQS 队列。有关消息保留期的更多信息，请参阅 *Amazon Simple Queue Service 开发人员指南*中[与消息相关的配额](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-quotas.html#quotas-messages)。您可以使用 Amazon SQS `[SetQueueAttributes](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SetQueueAttributes.html)` API 操作来更改消息保留策略。为了使您的应用程序更具弹性，我们建议将死信队列的最长保留期设置为 14 天。

## 如何将消息移至死信队列中？
<a name="how-messages-moved-into-dead-letter-queue"></a>

可以使用*重新驱动策略* 将您的消息移至死信队列中。重新驱动策略是一个引用死信队列 ARN 的 JSON 对象。`deadLetterTargetArn` 属性指定 ARN。ARN 必须指向与您的亚马逊 SNS 订阅位于 AWS 账户 相同和区域的亚马逊 SQS 队列。有关更多信息，请参阅 [为订阅配置 Amazon SNS 死信队列](sns-configure-dead-letter-queue.md)。

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

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

## 如何将消息移出死信队列？
<a name="how-to-move-messages-out-of-dead-letter-queue"></a>

可以通过两种方式将消息移出死信队列：
+ **避免编写 Amazon SQS 使用者逻辑** – 将死信队列设置为 Lambda 函数的事件源以耗尽死信队列。
+ **编写 Amazon SQS 使用者逻辑** — 使用 Amazon SQS API AWS 、SDK AWS CLI 或编写自定义使用者逻辑，用于轮询、处理和删除死信队列中的消息。

## 如何监控和记录死信队列？
<a name="how-to-monitor-log-dead-letter-queues"></a>

您可以使用亚马逊 CloudWatch 指标来监控与您的 Amazon SNS 订阅相关的死信队列。所有 Amazon SQS 队列每隔一分钟发布一次 CloudWatch 指标。有关更多信息，请参阅《[亚马逊*简单队列服务开发者指南》中的 Amazon* SQS 可用 CloudWatch 指标](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-available-cloudwatch-metrics.html)。所有带有死信队列的 Amazon SNS 订阅也会发布指标。 CloudWatch 有关更多信息，请参阅 [使用监控亚马逊 SNS 主题 CloudWatch](sns-monitoring-using-cloudwatch.md)。

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

**CloudWatch 警报设置示例**

1. 为该`ApproximateNumberOfMessagesVisible`指标创建[CloudWatch警报](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ConsoleAlarms.html)。

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

1. 指定在警报消失时要通知的 Amazon SNS **主题**。此 Amazon SNS 主题可以将告警通知传输到任何终端节点类型（例如，电子邮件地址、电话号码或移动寻呼机应用程序）。

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

# 为订阅配置 Amazon SNS 死信队列
<a name="sns-configure-dead-letter-queue"></a>

死信队列是一个 Amazon SQS 队列，Amazon SNS 订阅可以将其视为目标，用于存放无法成功传输给订阅用户的消息。由于客户端错误或服务器错误而无法传输的消息将保留在死信队列中，以进行进一步分析或重新处理。有关更多信息，请参阅[Amazon SNS 死信队列](sns-dead-letter-queues.md)和[Amazon SNS 消息传输重试](sns-message-delivery-retries.md)。

本页介绍如何使用、 AWS 软件开发工具包 AWS 管理控制台 AWS CLI、和 CloudFormation 为 Amazon SNS 订阅配置死信队列。

**注意**  
对于 [FIFO 主题](sns-fifo-topics.md)，您可以将 Amazon SQS 队列用作 Amazon SNS 订阅的死信队列。FIFO 主题订阅使用 FIFO 队列，而标准主题订阅使用标准队列。

## 先决条件
<a name="dead-letter-queue-prerequisites"></a>

在配置死信队列之前，请完成以下先决条件：

1. [创建名为 `MyTopic` 的 Amazon SNS 主题](sns-create-topic.md)。

1. [创建名为 `MyEndpoint` 的 Amazon SQS 队列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html)，以用作 Amazon SNS 订阅的终端节点。

1. （跳过 CloudFormation）[在队列中订阅主题](sns-sqs-as-subscriber.md)。

1. [创建另一个名为 `MyDeadLetterQueue` 的 Amazon SQS 队列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html)，以用作 Amazon SNS 订阅的死信队列。

1. 要向 Amazon SNS 委托人授予对 Amazon SQS API 操作的访问权限，请为 `MyDeadLetterQueue` 设置以下队列策略。

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": "sns.amazonaws.com"
         },
         "Action": "SQS:SendMessage",
         "Resource": "arn:aws:sqs:us-east-2:123456789012:MyDeadLetterQueue",
         "Condition": {
           "ArnEquals": {
             "aws:SourceArn": "arn:aws:sns:us-east-2:123456789012:MyTopic"
           }
         }
       }
     ]
   }
   ```

------

## 要为 Amazon SNS 订阅配置死信队列，请使用 AWS 管理控制台
<a name="configure-dead-letter-queue-aws-console"></a>

在开始本教程之前，请确保完成[先决条件](#dead-letter-queue-prerequisites)。

1. 登录 [Amazon SQS 控制台](https://console.aws.amazon.com/sqs/)。

1. [创建 Amazon SQS 队列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html)或使用现有队列，并在队列的 **Details**（详细信息）选项卡上记下队列的 ARN，例如：

   ```
   arn:aws:sqs:us-east-2:123456789012:MyDeadLetterQueue
   ```

1. 登录 [Amazon SNS 控制台](https://console.aws.amazon.com/sns/home)。

1. 在导航面板中，选择**订阅**。

1. 在 **Subscriptions (订阅)** 页面上，选择现有订阅，然后选择 **Edit (编辑)**。

1. 在 **Edit *1234a567-bc89-012d-3e45-6fg7h890123i*** (编辑) 页面上，展开 **Redrive policy (dead-letter queue) (重新驱动策略（死信队列）)** 部分，然后执行以下操作：

   1. 选择 **Enabled (已启用)**。

   1. 指定 Amazon SQS 队列的 ARN。

1. 选择**保存更改**。

   您的订阅将配置为使用死信队列。

## 使用软件开发工具包为 Amazon SNS 订阅配置死信队列 AWS
<a name="configure-dead-letter-queue-aws-sdk"></a>

在您运行此示例之前，请确保完成[先决条件](#dead-letter-queue-prerequisites)。

要使用 S AWS DK，必须使用您的凭据对其进行配置。有关更多信息，请参阅[《工具参考指南》和《*工具参考指南》中的共享配置AWS SDKs 和*凭据文件](https://docs.aws.amazon.com/sdkref/latest/guide/creds-config-files.html)。

以下代码示例演示了如何使用 `SetSubscriptionAttributesRedrivePolicy`。

------
#### [ Java ]

**适用于 Java 的 SDK 1.x**  
 还有更多相关信息 GitHub。在 [AWS 代码示例存储库](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/java/example_code/sns#code-examples)中查找完整示例，了解如何进行设置和运行。

```
// Specify the ARN of the Amazon SNS subscription.
String subscriptionArn =
    "arn:aws:sns:us-east-2:123456789012:MyEndpoint:1234a567-bc89-012d-3e45-6fg7h890123i";

// Specify the ARN of the Amazon SQS queue to use as a dead-letter queue.
String redrivePolicy =
    "{\"deadLetterTargetArn\":\"arn:aws:sqs:us-east-2:123456789012:MyDeadLetterQueue\"}";

// Set the specified Amazon SQS queue as a dead-letter queue
// of the specified Amazon SNS subscription by setting the RedrivePolicy attribute.
SetSubscriptionAttributesRequest request = new SetSubscriptionAttributesRequest()
    .withSubscriptionArn(subscriptionArn)
    .withAttributeName("RedrivePolicy")
    .withAttributeValue(redrivePolicy);
sns.setSubscriptionAttributes(request);
```

------

## 要为 Amazon SNS 订阅配置死信队列，请使用 AWS CLI
<a name="configure-dead-letter-queue-aws-cli"></a>

在开始本教程之前，请确保完成[先决条件](#dead-letter-queue-prerequisites)。

1. 安装和配置 AWS CLI。有关更多信息，请参阅 [https://docs.aws.amazon.com/cli/latest/userguide/](https://docs.aws.amazon.com/cli/latest/userguide/)。

1. 使用以下命令。

   ```
   aws sns set-subscription-attributes \
   --subscription-arn arn:aws:sns:us-east-2:123456789012:MyEndpoint:1234a567-bc89-012d-3e45-6fg7h890123i
   --attribute-name RedrivePolicy
   --attribute-value "{\"deadLetterTargetArn\": \"arn:aws:sqs:us-east-2:123456789012:MyDeadLetterQueue\"}"
   ```

## 使用为 Amazon SNS 订阅配置死信队列 CloudFormation
<a name="configure-dead-letter-queue-aws-cloudformation"></a>

在开始本教程之前，请确保完成[先决条件](#dead-letter-queue-prerequisites)。

1. 将以下 JSON 代码复制到名为 `MyDeadLetterQueue.json` 的文件中。

   ```
   {
     "Resources": {
       "mySubscription": {
         "Type" : "AWS::SNS::Subscription",
         "Properties" : {
           "Protocol": "sqs",
           "Endpoint": "arn:aws:sqs:us-east-2:123456789012:MyEndpoint",
           "TopicArn": "arn:aws:sns:us-east-2:123456789012:MyTopic",
           "RedrivePolicy": {
             "deadLetterTargetArn":
               "arn:aws:sqs:us-east-2:123456789012:MyDeadLetterQueue"
           }
         }
       }
     }
   }
   ```

1. 登录 [CloudFormation 控制台](https://console.aws.amazon.com/cloudformation/)。

1. 在 **Select Template (选择模板)** 页面上，选择 **Upload a template to Amazon S3 (将模板上传到 Amazon S3)**，再选择您的 `MyDeadLetterQueue.json` 文件，然后选择 **Next (下一步)**。

1. 在 **Specify Details**（指定详细信息）页面上，为 **Stack Name**（堆栈名称）输入 `MyDeadLetterQueue`，然后选择 **Next**（下一步）。

1. 在**选项**页面上，选择**下一步**。

1. 在 **Review** 页面上，选择 **Create **。

   CloudFormation 开始创建`MyDeadLetterQueue`堆栈并显示 **CREATE\$1IN\$1** PROGRESS 状态。该过程完成后， CloudFormation 将显示 “**创建\$1完成**” 状态。