

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

# Amazon SNS 消息传输
<a name="message-delivery"></a>

本主题介绍 Amazon SNS 如何处理各种场景中的消息传送。您将了解原始消息传输，其中 Amazon SNS 以未经修改的原始格式将消息传送到端点。您还将了解如何将消息从 Amazon SNS 主题发送到 AWS 账户另一个 Amazon SQS 队列，从而深入了解跨账户消息传送。

本主题提供有关将 Amazon SNS 消息传送到 AWS 区域不同的 Amazon SQS 队列或 Lambda 函数的信息、跨区域交付的工作原理以及所涉及的注意事项。

此外，您还将了解如何监控和解释消息传送状态，从而提供有关消息是否成功送达或遇到问题的关键信息。如果消息传送失败，您将了解消息传送重试流程，包括 Amazon SNS 如何自动尝试重新传送消息以确保消息到达预期目标。本主题还讨论了如何使用死信队列来捕获多次尝试后无法传送的消息，从而使您能够有效地分析和排除这些失败。

# Amazon SNS 原始消息传输
<a name="sns-large-payload-raw-message-delivery"></a>

为避免使 [扇出到 Firehose 传输流](sns-firehose-as-subscriber.md)、[Amazon SQS](sns-sqs-as-subscriber.md) 和 [HTTP/S](sns-http-https-endpoint-as-subscriber.md) 端点处理 JSON 格式的消息，Amazon SNS 支持原始消息传输：
+ 当您为 Amazon SQS 端点启用原始消息传输时，将从已发布的消息中删除任何 Amazon SNS 元数据，并按原样发送消息。
+ 当您为 HTTP/S 终端节点启用原始消息传送时，其值设置为`true`的 HTTP 标头`x-amz-sns-rawdelivery`将添加到消息中，表示消息已在没有 JSON 格式的情况下发布。
+ 当您为 HTTP/S 端点启用原始消息传输时，将传递消息正文、客户端 IP 和所需的标头。当您指定消息属性时，将不会发送它。
+ 当您为 Firehose 端点启用原始消息传输时，将传输消息正文。当您指定消息属性时，将不会发送它。

要使用 AWS SDK 启用原始消息传送，必须使用 `SetSubscriptionAttribute` API 操作并将`RawMessageDelivery`属性的值设置为`true`。

## 使用启用原始消息传送 AWS 管理控制台
<a name="raw-message-console"></a>

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

1. 在导航面板上，选择**主题**。

1. 在**主题**页面上，选择订阅了 Firehose、Amazon SQS 或终端节点的主题。 HTTP/S 

1. 在该***MyTopic***页面的**订阅**部分，选择订阅并选择**编辑**。

1. 在**编辑*EXAMPLE1-23bc-4567-d890-ef12g3hij456***页面的**详细信息**部分，选择**启用原始消息传送**。

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

## 消息格式示例
<a name="raw-message-examples"></a>

在以下示例中，同一消息将发送到同一 Amazon SQS 队列两次。唯一的区别是第一条消息禁用原始消息传输，第二条消息则启用该传输。
+ 原始消息传输**已禁用**

  ```
  {
    "Type": "Notification",
    "MessageId": "dc1e94d9-56c5-5e96-808d-cc7f68faa162",
    "TopicArn": "arn:aws:sns:us-east-2:111122223333:ExampleTopic1",
    "Subject": "TestSubject",
    "Message": "This is a test message.",
    "Timestamp": "2021-02-16T21:41:19.978Z",
    "SignatureVersion": "1",
    "Signature": "FMG5tlZhJNHLHUXvZgtZzlk24FzVa7oX0T4P03neeXw8ZEXZx6z35j2FOTuNYShn2h0bKNC/zLTnMyIxEzmi2X1shOBWsJHkrW2xkR58ABZF+4uWHEE73yDVR4SyYAikP9jstZzDRm+bcVs8+T0yaLiEGLrIIIL4esi1llhIkgErCuy5btPcWXBdio2fpCRD5x9oR6gmE/rd5O7lX1c1uvnv4r1Lkk4pqP2/iUfxFZva1xLSRvgyfm6D9hNklVyPfy+7TalMD0lzmJuOrExtnSIbZew3foxgx8GT+lbZkLd0ZdtdRJlIyPRP44eyq78sU0Eo/LsDr0Iak4ZDpg8dXg==",
    "SigningCertURL": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-010a507c1833636cd94bdb98bd93083a.pem",
    "UnsubscribeURL": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:111122223333:ExampleTopic1:e1039402-24e7-40a3-a0d4-797da162b297"
  }
  ```
+ 原始消息传输**已启用**

  ```
  This is a test message.
  ```

## Amazon SQS 订阅的消息属性和原始消息传送
<a name="message-atttributes-raw-message-delivery-sqs"></a>

Amazon SNS 支持传输消息属性，从而让您提供与消息相关的结构化元数据项目（如时间戳、地理空间数据、签名和标识符）。对于 Amazon SQS 订阅，在启用**原始消息传输**时，最多可以发送 10 个消息属性。要发送 10 个以上的消息属性，您必须禁用“原始消息传输”。Amazon SNS 会丢弃所具有的消息属性（定向到启用了原始消息传输的 Amazon SQS 订阅）超过 10 个的消息，将其视为客户端错误。

# 将 Amazon SNS 消息发送到不同账户中的 Amazon SQS 队列
<a name="sns-send-message-to-sqs-cross-account"></a>

本文档介绍如何通过另一个账户中的一个或多个 Amazon SQS 队列订阅将通知发布到 Amazon SNS 主题。如果主题和队列在同一账户下，那么您可以采用相同方法设置主题和队列（参阅 [将 Amazon SNS 通知扇出到 Amazon SQS 队列进行异步处理](sns-sqs-as-subscriber.md)）。主要区别在于您处理订阅确认的方式，这取决于您如何为队列订阅主题。

最佳做法是尽可能遵循[队列拥有者创建订阅](#SendMessageToSQS.cross.account.queueowner)部分中引用的步骤，因为当队列拥有者创建订阅时会自动进行确认。

**注意**  
如果 Amazon SQS 队列有大量消息，建议队列所有者创建订阅。

## 队列拥有者创建订阅
<a name="SendMessageToSQS.cross.account.queueowner"></a>

创建 Amazon SQS 队列的账户是队列拥有者。如果订阅由队列所有者创建，那么此订阅无需确认。一旦 `Subscribe` 操作完成后，队列即开始接收来自主题的通知。主题所有者必须提供队列所有者的账户权限，允许其对主题调用 `Subscribe` 操作，从而让队列所有者订阅主题所有者的主题。

### 步骤 1：使用设置主题策略 AWS 管理控制台
<a name="sns-tutorial-set-topic-policy"></a>

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

1. 在导航面板上，选择**主题**。

1. 选择一个主题，然后选择 **Edit**（编辑）。

1. 在 **“编辑” *MyTopic*** 页面上，展开 “**访问策略**” 部分。

1. 输入以下策略：

   ```
   {
      "Statement": [
         {
            "Effect": "Allow",
            "Principal": {
               "AWS": "111122223333"
            },
            "Action": "sns:Subscribe",
            "Resource": "arn:aws:sns:us-east-2:123456789012:MyTopic"
         }
      ]
   }
   ```

   此策略授予账户 `111122223333` 对账户 `123456789012` 中的 `MyTopic` 调用 `sns:Subscribe` 的权限。

   具有账户 `111122223333` 的凭证的用户可以订阅 `MyTopic`。此权限允许账户 ID 将权限委派给其 IAM 用户/角色。只有根账户或管理员用户才可以调用 `sns:Subscribe`。IAM 还 user/role 必须`sns:subscribe`允许其队列进行订阅。

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

   拥有账户凭证的用户`111122223333`可以订阅 MyTopic。

### 第 2 步：要将 Amazon SQS 队列订阅添加到另一个 AWS 账户 主题中的某个主题，请使用 AWS 管理控制台
<a name="sns-tutorial-add-sqs-subscription-to-sns-topic-another-account"></a>

在开始之前，请确保您拥有主题和队列 ARNs 的[权限，并且您已向该主题授予向队列发送消息的](subscribe-sqs-queue-to-sns-topic.md#SendMessageToSQS.sqs.permissions)权限。

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

1. 在导航窗格中，选择 **Queues**（队列）。

1.  从队列列表中，选择 **queue**（排队）以订阅 Amazon SNS 主题。

1. 选择 **Subscribe to Amazon SNS topic**（订阅 Amazon SNS 主题）。

1. 从 **Specify an Amazon SNS topic available for this queue menu**（指定可用于此队列菜单的 Amazon SNS 主题）中，选择队列的 **Amazon SNS topic**（Amazon SNS 主题）。

1. 选择 **Enter Amazon SNS topic ARN**（输入 Amazon SNS 主题 ARN），然后输入主题的 **Amazon Resource Name (ARN)**。

1. 选择**保存**。
**注意**  
要能够与服务通信，队列必须具有 Amazon SNS 的权限。
由于您是队列的所有者，因此您无需确认订阅。

## 非队列所有者用户创建订阅
<a name="SendMessageToSQS.cross.account.notqueueowner"></a>

创建订阅但不是队列所有者的任何用户都必须确认订阅。

使用 `Subscribe` 操作时，Amazon SNS 向队列发送订阅确认。订阅将显示在 Amazon SNS 控制台中，其订阅 ID 设置为**等待确认**。

要确认订阅，具有从队列中读取消息的权限的用户必须检索订阅确认 URL，而且订阅拥有者必须使用订阅确认 URL 以确认订阅。确认订阅前，向主题发布的通知不会发送至队列。要确认订阅，您可以使用 Amazon SQS 控制台或 `[ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/Query_QueryReceiveMessage.html)` 操作。

**注意**  
在为终端节点订阅主题之前，请通过为队列设置 `sqs:SendMessage` 权限来确保队列可以接收来自主题的消息。有关更多信息，请参阅 [步骤 2. 为向 Amazon SQS 队列发送消息的 Amazon SNS 主题授予权限](subscribe-sqs-queue-to-sns-topic.md#SendMessageToSQS.sqs.permissions)。

### 步骤 1：要将 Amazon SQS 队列订阅添加到另一个 AWS 账户 主题中的某个主题，请使用 AWS 管理控制台
<a name="sns-tutorial-add-sqs-subscription-to-sns-topic-another-account"></a>

在开始之前，请确保您拥有主题和队列 ARNs 的[权限，并且您已向该主题授予向队列发送消息的](subscribe-sqs-queue-to-sns-topic.md#SendMessageToSQS.sqs.permissions)权限。

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

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

1. 在**订阅**页面上，选择**创建订阅**。

1.  在**创建订阅**页上的**详细信息**部分，执行以下操作：

   1. 对于 **Topic ARN (主题 ARN)**，输入主题的 ARN。

   1. 对于 **Protocol**（协议），选择 **Amazon SQS**。

   1. 对于 **Endpoint**（终端节点），输入队列的 ARN。

   1. 选择 **Create subscription**（创建订阅）。
**注意**  
要能够与服务通信，队列必须具有 Amazon SNS 的权限。

下面是允许 Amazon SNS 主题向 Amazon SQS 队列发送消息的示例策略声明。

```
{
   "Sid": "Stmt1234",
   "Effect": "Allow",
   "Principal": "*",
   "Action": "sqs:SendMessage",
   "Resource": "arn:aws:sqs:us-west-2:111111111111:QueueName",
   "Condition": {
      "ArnEquals": {
         "aws:SourceArn": "arn:aws:sns:us-west-2:555555555555:TopicName"
      }
   }
}
```

### 第 2 步：使用确认订阅 AWS 管理控制台
<a name="sns-tutorial-confirm-subscription-console"></a>

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

1. 选择主题处于等待订阅阶段的队列。

1. 选择 **Send and receive messages**（发送和接收消息），然后选择 **Poll for messages**（轮询消息）。

   队列中会收到一条带有订阅确认的消息。

1. 在 **Body**（正文）列中，执行以下操作：

   1. 选择 **More Details**（更多详情）。

   1. 在 **Message Details**（消息详细信息）对话框中，找到并记下 **SubscribeURL** 值。这是您的订阅链接（下面的示例）。有关 API 令牌验证的更多详细信息，请参阅《Amazon SNS API 参考》中的 [https://docs.aws.amazon.com/sns/latest/api/API_ConfirmSubscription.html](https://docs.aws.amazon.com/sns/latest/api/API_ConfirmSubscription.html)。

      ```
      https://sns.us-west-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-east-2:123456789012:MyTopic&Token=2336412f37fb...
      ```

   1. 记下订阅确认链接。必须将 URL 从队列拥有者传递给订阅拥有者。订阅拥有者必须在 [Amazon SNS 控制台](https://console.aws.amazon.com/sns/v3/home)中输入此 URL。

1. 以**订阅拥有者** 身份登录 [Amazon SNS 控制台](https://console.aws.amazon.com/sns/v3/home)。订阅拥有者执行确认。

1. 选择相关**主题**。

1. 在主题的订阅清单表格中选择相关**订阅**。它被标记为“Pending confirmation”（等待确认）。

1. 选择 **Confirm subscription**（确认订阅）。

1. 将出现一个提示订阅确认链接的模态框。**粘贴** 订阅确认链接。

1. 在模态框中选择 **Confirm subscription**（确认订阅）。

   将显示 XML 响应，例如：

   ```
   <ConfirmSubscriptionResponse>
      <ConfirmSubscriptionResult>
         <SubscriptionArn>arn:aws:sns:us-east-2:123456789012:MyTopic:1234a567-bc89-012d-3e45-6fg7h890123i</SubscriptionArn>
      </ConfirmSubscriptionResult>
      <ResponseMetadata>
         <RequestId>abcd1efg-23hi-jkl4-m5no-p67q8rstuvw9</RequestId>
      </ResponseMetadata>
   </ConfirmSubscriptionResponse>
   ```

   已订阅队列已准备好接收来自主题的消息。

1. （可选）如果您在 Amazon SNS 控制台中查看主题订阅，则可以看到**等待确认**消息已被 **Subscription ID**（订阅 ID）列中的订阅 ARN 取代。

## 如何强制订阅要求对取消订阅请求进行身份验证？
<a name="sns-send-message-to-sqs-cross-account-AuthenticateOnUnsubscribe"></a>

订阅拥有者必须在订阅确认后将 `AuthenticateOnUnsubscribe` 标志设置为 true。
+ 如果订阅由队列拥有者创建，则 `AuthenticateOnUnsubscribe` 自动设置为 true。
+ 在没有身份验证的情况下导航到订阅确认链接时，无法将 `AuthenticateOnUnsubscribe` 设置为 true。

# 向不同区域的亚马逊 SQS 队列 AWS Lambda 或函数发送 Amazon SNS 消息
<a name="sns-cross-region-delivery"></a>

Amazon SNS 支持跨区域传输，无论是默认启用的区域还是[可选择加入的区域](#opt-in-regions)。有关 Amazon SNS 支持的 AWS 区域的当前列表（包括选择加入的区域），请参阅《Amazon Web Services 一般参考》**中的 [Amazon Simple Notification Service 端点和限额](https://docs.aws.amazon.com/general/latest/gr/sns.html)。

Amazon SNS 支持跨区域传输通知到 Amazon SQS 队列以及 AWS Lambda 函数。当其中一个区域是选择加入的区域时，您必须在订阅资源的策略中指定不同的 Amazon SNS 服务委托人。

Amazon SNS 订阅命令必须在相应区域中托管 Amazon SNS 的区域内执行。例如，如果 Amazon SNS 位于 us-east-1 区域的“A”账户中，而 Lambda 函数位于 us-east-2 区域的“B”账户中，则必须在 us-east-1 区域的“A”账户中执行订阅 CLI 命令。

## 选择加入的区域
<a name="opt-in-regions"></a>

Amazon SNS 支持以下选择加入的区域：


| 区域名称 | Region | 
| --- | --- | 
|  非洲（开普敦）区域  |  af-south-1  | 
|  亚太地区（香港）区域  |  ap-east-1  | 
|  亚太地区（海得拉巴）区域  |  ap-south-2  | 
|  亚太地区（雅加达）区域  |  ap-southeast-3  | 
|  亚太地区（墨尔本）区域  |  ap-southeast-4  | 
|  欧洲地区（米兰）  |  eu-south-1  | 
|  欧洲（西班牙）区域  |  eu-south-2  | 
|  欧洲（苏黎世）  |  eu-central-2  | 
|  以色列（特拉维夫）区域  |  il-central-1  | 
|  中东（巴林）区域  |  me-south-1  | 
|  中东（阿联酋）区域  |  me-central-1  | 

*有关启用可选区域的信息，请参阅中的[Amazon Web Services 一般参考管理 AWS 区域](https://docs.aws.amazon.com/general/latest/gr/rande-manage.html)。*

使用 Amazon SNS 将消息从选择加入的区域传输到默认启用的区域时，必须更改为队列创建的资源策略。将委托人 `sns.amazonaws.com` 替换为 `sns.<opt-in-region>.amazonaws.com`。例如：
+  要为美国东部（弗吉尼亚州北部）的 Amazon SQS 队列订阅亚太地区（香港）的 Amazon SNS 主题，请将队列策略中的主体更改为 `sns.ap-east-1.amazonaws.com`。选择加入区域包括 2019 年 3 月 20 日之后推出的任何区域，包括亚太地区（香港）、亚太地区（雅加达）、中东（巴林）、欧盟（米兰）和非洲（开普敦）。2019 年 3 月 20 日之前推出的区域默认情况下处于启用状态。  
**对于 Amazon SQS 的跨区域传输支持**    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sns/latest/dg/sns-cross-region-delivery.html)

  以下是访问策略声明的示例，该声明允许选择加入区域 (af-south-1) 中的亚马逊 SNS 主题发送到某个区域 (us-east-1) 中的亚马逊 SQS 队列。enabled-by-default 它在路径 `Statement`/`Principal`/`Service` 下包含必要的区域化服务主体配置。

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

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Id": "__default_policy_ID",
      "Statement": [
          {
              "Sid": "allow_sns_arn:aws:sns:af-south-1:111111111111:source_topic_name",
              "Effect": "Allow",
              "Principal": {
                  "Service": "sns.af-south-1.amazonaws.com"
              },
              "Action": "SQS:SendMessage",
              "Resource": "arn:aws:sqs:us-west-1:111111111111:destination_queue_name",
              "Condition": {
                  "ArnLike": {
                      "aws:SourceArn": "arn:aws:sns:af-south-1:111111111111:source_topic_name"
                  }
              }
          }
      ]
  }
  ```

------
+  要为美国东部（弗吉尼亚北部）的 AWS Lambda 函数订阅亚太地区（香港）的 Amazon SNS 主题，请将 AWS Lambda 功能策略中的主体更改为。`sns.ap-east-1.amazonaws.com`选择加入区域包括 2019 年 3 月 20 日之后推出的任何区域，包括亚太地区（香港）、亚太地区（雅加达）、中东（巴林）、欧盟（米兰）和非洲（开普敦）。2019 年 3 月 20 日之前推出的区域默认情况下处于启用状态。  
**跨区域配送支持 AWS Lambda**    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sns/latest/dg/sns-cross-region-delivery.html)

# Amazon SNS 消息传输状态
<a name="sns-topic-attributes"></a>

对于使用下列 Amazon SNS 端点的主题，Amazon SNS 支持记录发送到这些主题的通知消息的传输状态：
+ Amazon Data Firehose
+ Amazon Simple Queue Service
+ AWS Lambda
+ HTTPS
+ 平台应用程序终端节点

发送状态日志将发送到 Amazon CloudWatch Logs，从而提供对消息传输操作的见解。这些日志可以帮助您：
+ 确定消息是否已成功传输到端点。
+ 识别从端点发送到 Amazon SNS 的响应。
+ 衡量消息停留时间（从发布时间戳到移交给端点之间的时间）。

您可以使用 AWS 管理控制台、 AWS SDKs、查询 API 或配置传送状态日志记录 AWS CloudFormation。

# 配置传输状态日志记录的先决条件
<a name="topics-attrib-prereq"></a>

本主题概述了允许 Amazon SNS 向其写入传输日志所必需的 IAM 权限， CloudWatch 并解释了默认日志组命名约定。这可确保您拥有正确的设置和访问权限，以监控和分析日志中的消息传送 CloudWatch 日志。

**所需的 IAM 权限**

为记录交付状态而附加的 IAM 角色必须包含以下权限，才能让 Amazon SNS 写入 CloudWatch 日志。您可以在设置过程中使用具有这些权限的现有角色，也可以创建新角色。

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

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    }
  ]
}
```

------

**日志组命名约定**

默认情况下，Amazon SNS 使用以下命名约定为传输状态 CloudWatch 日志创建日志组。该组中的日志流对应于端点协议（例如 Lambda、Amazon SQS）。确保您有权在日志控制台中查看这些 CloudWatch 日志。

```
sns/<region>/<account-id>/<topic-name>
```

# 使用配置传送状态日志 AWS 管理控制台
<a name="topics-attrib"></a>

本主题介绍如何为 Amazon SNS 主题启用消息传输状态日志，包括配置日志设置、分配 IAM 角色以及验证日志是否捕获传输 CloudWatch 日志以进行监控和故障排除。

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

1. 在导航面板上，选择**主题**。

1. 选择所需的**主题**，然后选择**编辑**。

1. 展开**传输状态日志记录**部分。

1. 选择要为其启用日志记录功能的**协议**（例如 HTTP、Lambda、Amazon SQS）。

1. 输入**成功采样率**，即您希望接收 CloudWatch 日志的成功消息的百分比。

1. 在 **IAM 角色**部分，您必须为**成功**和**失败**日志记录配置角色：
   + **使用现有服务角色**-选择具有 Amazon SNS 写入日志所需权限的现有 IAM 角色。 CloudWatch
   + **创建新的服务角色** – 选择**创建新角色**，以便在 IAM 控制台中为成功和失败的传输定义 IAM 角色。有关权限的详细信息，请参阅[配置传输状态日志记录的先决条件](topics-attrib-prereq.md)。

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

   启用日志记录后，您可以查看和解析包含消息传送状态的 CloudWatch 日志。有关使用的更多信息 CloudWatch，请参阅[CloudWatch文档](https://aws.amazon.com/documentation/cloudwatch)。

**验证日志设置**

1. 登录 CloudWatch 日志控制台。

1. 找到名为 `sns/<region>/<account-id>/<topic-name>` 的日志组。

1. 确保已配置的端点协议存在日志流。

1. 向主题发送测试消息，并确认日志条目是否出现，该日志条目会表明传输成功还是失败。

# 使用配置传送状态日志 AWS SDKs
<a name="msg-status-sdk"></a>

 AWS SDKs 提供了多种 APIs 语言来设置消息传送状态记录的主题属性。例如，使用 [SetTopicAttributes](https://docs.aws.amazon.com/sns/latest/api/API_SetTopicAttributes.html)API 来配置：
+ `LambdaSuccessFeedbackRoleArn` – 向 Lambda 端点传输成功消息的 IAM 角色。
+ `LambdaSuccessFeedbackSampleRate` – 传输到 Lambda 端点的成功消息采样率。
+ `LambdaFailureFeedbackRoleArn` – 向 Lambda 端点传输失败消息的 IAM 角色。

** AWS CLI 命令示例**

```
aws sns set-topic-attributes \
    --topic-arn arn:aws:sns:us-west-2:123456789012:MyTopic \
    --attribute-name LambdaSuccessFeedbackRoleArn \
    --attribute-value arn:aws:iam::123456789012:role/MyFeedbackRole
```

## 主题属性
<a name="topic-attributes"></a>

对消息传输状态使用下列主题属性名称值：

**HTTP**
+ `HTTPSuccessFeedbackRoleArn` – 订阅到 HTTP 端点的 Amazon SNS 主题的成功消息传输状态。
+ `HTTPSuccessFeedbackSampleRate` – 订阅到 HTTP 端点的 Amazon SNS 主题的成功消息采样百分比。
+ `HTTPFailureFeedbackRoleArn` – 订阅到 HTTP 端点的 Amazon SNS 主题的失败消息传输状态。

**Amazon Data Firehose**
+ `FirehoseSuccessFeedbackRoleArn` – 订阅到 Amazon Data Firehose 端点的 Amazon SNS 主题的成功消息传输状态。
+ `FirehoseSuccessFeedbackSampleRate` – 订阅到 Amazon Data Firehose 端点的 Amazon SNS 主题的成功消息采样百分比。
+ `FirehoseFailureFeedbackRoleArn` – 订阅到 Amazon Data Firehose 端点的 Amazon SNS 主题的失败消息传输状态。

**AWS Lambda**
+ `LambdaSuccessFeedbackRoleArn` – 订阅到 Lambda 端点的 Amazon SNS 主题的成功消息传输状态。
+ `LambdaSuccessFeedbackSampleRate` – 订阅到 Lambda 端点的 Amazon SNS 主题的成功消息采样百分比。
+ `LambdaFailureFeedbackRoleArn` – 订阅到 Lambda 端点的 Amazon SNS 主题的失败消息传输状态。

**平台应用程序端点**
+ `ApplicationSuccessFeedbackRoleArn`— 订阅应用程序终端节点的 Amazon SNS 主题的成功消息传输状态。 AWS 
+ `ApplicationSuccessFeedbackSampleRate` – 订阅到 AWS 应用程序端点的 Amazon SNS 主题的成功消息采样百分比。
+ `ApplicationFailureFeedbackRoleArn`— 订阅应用程序终端节点的 Amazon SNS 主题的消息传输失败状态。 AWS 
**注意**  
此外，您还可以配置应用程序属性，直接将传输状态记录到推送通知服务中。有关更多信息，请参阅[使用用于消息传输状态的 Amazon SNS 应用程序属性](https://docs.aws.amazon.com/sns/latest/dg/sns-msg-status.html)。

**Amazon SQS**
+ `SQSSuccessFeedbackRoleArn` – 订阅到 Amazon SQS 端点的 Amazon SNS 主题的成功消息传输状态。
+ `SQSSuccessFeedbackSampleRate` – 订阅到 Amazon SQS 端点的 Amazon SNS 主题的成功消息采样百分比。
+ `SQSFailureFeedbackRoleArn` – 订阅到 Amazon SQS 端点的 Amazon SNS 主题的失败消息传输状态。

平台应用程序终端节点的日志与其他终端节点一样写入同一个 CloudWatch 日志组。

**注意**  
 `<ENDPOINT>SuccessFeedbackRoleArn`和`<ENDPOINT>FailureFeedbackRoleArn`属性用于向 Amazon SNS 授予代表您使用 CloudWatch 日志的写入权限。`<ENDPOINT>SuccessFeedbackSampleRate` 属性用于指定成功传输消息的采样率百分比 (0-100)。配置该`<ENDPOINT>FailureFeedbackRoleArn`属性后，所有失败的消息传送都会生成 CloudWatch 日志。

# AWS 用于配置主题属性的 SDK 示例
<a name="topic-attributes-sdks"></a>

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

------
#### [ CLI ]

**AWS CLI**  
**为主题设置属性**  
以下 `set-topic-attributes` 示例为指定主题设置 `DisplayName` 属性。  

```
aws sns set-topic-attributes \
    --topic-arn arn:aws:sns:us-west-2:123456789012:MyTopic \
    --attribute-name DisplayName \
    --attribute-value MyTopicDisplayName
```
此命令不生成任何输出。  
+  有关 API 的详细信息，请参阅*AWS CLI 命令参考[SetTopicAttributes](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sns/set-topic-attributes.html)*中的。

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

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

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.SetTopicAttributesRequest;
import software.amazon.awssdk.services.sns.model.SetTopicAttributesResponse;
import software.amazon.awssdk.services.sns.model.SnsException;

/**
 * Before running this Java V2 code example, set up your development
 * environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */
public class SetTopicAttributes {

    public static void main(String[] args) {
        final String usage = """

                Usage:    <attribute> <topicArn> <value>

                Where:
                   attribute - The attribute action to use. Valid parameters are: Policy | DisplayName | DeliveryPolicy .
                   topicArn - The ARN of the topic.\s
                   value - The value for the attribute.
                """;

        if (args.length < 3) {
            System.out.println(usage);
            System.exit(1);
        }

        String attribute = args[0];
        String topicArn = args[1];
        String value = args[2];

        SnsClient snsClient = SnsClient.builder()
                .region(Region.US_EAST_1)
                .build();

        setTopAttr(snsClient, attribute, topicArn, value);
        snsClient.close();
    }

    public static void setTopAttr(SnsClient snsClient, String attribute, String topicArn, String value) {
        try {
            SetTopicAttributesRequest request = SetTopicAttributesRequest.builder()
                    .attributeName(attribute)
                    .attributeValue(value)
                    .topicArn(topicArn)
                    .build();

            SetTopicAttributesResponse result = snsClient.setTopicAttributes(request);
            System.out.println(
                    "\n\nStatus was " + result.sdkHttpResponse().statusCode() + "\n\nTopic " + request.topicArn()
                            + " updated " + request.attributeName() + " to " + request.attributeValue());

        } catch (SnsException e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
    }
}
```
+  有关 API 的详细信息，请参阅 *AWS SDK for Java 2.x API 参考[SetTopicAttributes](https://docs.aws.amazon.com/goto/SdkForJavaV2/sns-2010-03-31/SetTopicAttributes)*中的。

------
#### [ JavaScript ]

**适用于 JavaScript (v3) 的软件开发工具包**  
 还有更多相关信息 GitHub。在 [AWS 代码示例存储库](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javascriptv3/example_code/sns#code-examples) 中查找完整示例，了解如何进行设置和运行。
在单独的模块中创建客户端并将其导出。  

```
import { SNSClient } from "@aws-sdk/client-sns";

// The AWS Region can be provided here using the `region` property. If you leave it blank
// the SDK will default to the region set in your AWS config.
export const snsClient = new SNSClient({});
```
导入 SDK 和客户端模块，然后调用 API。  

```
import { SetTopicAttributesCommand } from "@aws-sdk/client-sns";
import { snsClient } from "../libs/snsClient.js";

export const setTopicAttributes = async (
  topicArn = "TOPIC_ARN",
  attributeName = "DisplayName",
  attributeValue = "Test Topic",
) => {
  const response = await snsClient.send(
    new SetTopicAttributesCommand({
      AttributeName: attributeName,
      AttributeValue: attributeValue,
      TopicArn: topicArn,
    }),
  );
  console.log(response);
  // {
  //   '$metadata': {
  //     httpStatusCode: 200,
  //     requestId: 'd1b08d0e-e9a4-54c3-b8b1-d03238d2b935',
  //     extendedRequestId: undefined,
  //     cfId: undefined,
  //     attempts: 1,
  //     totalRetryDelay: 0
  //   }
  // }
  return response;
};
```
+  有关更多信息，请参阅[《适用于 JavaScript 的 AWS SDK Developer Guide》](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/sns-examples-managing-topics.html#sns-examples-managing-topicsstttopicattributes)。
+  有关 API 的详细信息，请参阅 *适用于 JavaScript 的 AWS SDK API 参考[SetTopicAttributes](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/sns/command/SetTopicAttributesCommand)*中的。

------
#### [ Kotlin ]

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

```
suspend fun setTopAttr(
    attribute: String?,
    topicArnVal: String?,
    value: String?,
) {
    val request =
        SetTopicAttributesRequest {
            attributeName = attribute
            attributeValue = value
            topicArn = topicArnVal
        }

    SnsClient.fromEnvironment { region = "us-east-1" }.use { snsClient ->
        snsClient.setTopicAttributes(request)
        println("Topic ${request.topicArn} was updated.")
    }
}
```
+  有关 API 的详细信息，请参阅适用[SetTopicAttributes](https://sdk.amazonaws.com/kotlin/api/latest/index.html)于 K *otlin 的AWS SDK API 参考*。

------
#### [ PHP ]

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

```
require 'vendor/autoload.php';

use Aws\Exception\AwsException;
use Aws\Sns\SnsClient;


/**
 * Configure the message delivery status attributes for an Amazon SNS Topic.
 *
 * This code expects that you have AWS credentials set up per:
 * https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials.html
 */

$SnSclient = new SnsClient([
    'profile' => 'default',
    'region' => 'us-east-1',
    'version' => '2010-03-31'
]);
$attribute = 'Policy | DisplayName | DeliveryPolicy';
$value = 'First Topic';
$topic = 'arn:aws:sns:us-east-1:111122223333:MyTopic';

try {
    $result = $SnSclient->setTopicAttributes([
        'AttributeName' => $attribute,
        'AttributeValue' => $value,
        'TopicArn' => $topic,
    ]);
    var_dump($result);
} catch (AwsException $e) {
    // output error message if fails
    error_log($e->getMessage());
}
```
+  有关 API 的详细信息，请参阅 *适用于 PHP 的 AWS SDK API 参考[SetTopicAttributes](https://docs.aws.amazon.com/goto/SdkForPHPV3/sns-2010-03-31/SetTopicAttributes)*中的。

------
#### [ Ruby ]

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

```
# Service class to enable an SNS resource with a specified policy
class SnsResourceEnabler
  # Initializes the SnsResourceEnabler with an SNS resource client
  #
  # @param sns_resource [Aws::SNS::Resource] The SNS resource client
  def initialize(sns_resource)
    @sns_resource = sns_resource
    @logger = Logger.new($stdout)
  end

  # Sets a policy on a specified SNS topic
  #
  # @param topic_arn [String] The ARN of the SNS topic
  # @param resource_arn [String] The ARN of the resource to include in the policy
  # @param policy_name [String] The name of the policy attribute to set
  def enable_resource(topic_arn, resource_arn, policy_name)
    policy = generate_policy(topic_arn, resource_arn)
    topic = @sns_resource.topic(topic_arn)

    topic.set_attributes({
                           attribute_name: policy_name,
                           attribute_value: policy
                         })
    @logger.info("Policy #{policy_name} set successfully for topic #{topic_arn}.")
  rescue Aws::SNS::Errors::ServiceError => e
    @logger.error("Failed to set policy: #{e.message}")
  end

  private

  # Generates a policy string with dynamic resource ARNs
  #
  # @param topic_arn [String] The ARN of the SNS topic
  # @param resource_arn [String] The ARN of the resource
  # @return [String] The policy as a JSON string
  def generate_policy(topic_arn, resource_arn)
    {
      Version: '2008-10-17',
      Id: '__default_policy_ID',
      Statement: [{
        Sid: '__default_statement_ID',
        Effect: 'Allow',
        Principal: { "AWS": '*' },
        Action: ['SNS:Publish'],
        Resource: topic_arn,
        Condition: {
          ArnEquals: {
            "AWS:SourceArn": resource_arn
          }
        }
      }]
    }.to_json
  end
end

# Example usage:
if $PROGRAM_NAME == __FILE__
  topic_arn = 'MY_TOPIC_ARN' # Should be replaced with a real topic ARN
  resource_arn = 'MY_RESOURCE_ARN' # Should be replaced with a real resource ARN
  policy_name = 'POLICY_NAME' # Typically, this is "Policy"

  sns_resource = Aws::SNS::Resource.new
  enabler = SnsResourceEnabler.new(sns_resource)

  enabler.enable_resource(topic_arn, resource_arn, policy_name)
end
```
+  有关更多信息，请参阅《适用于 Ruby 的 AWS SDK 开发人员指南》[https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/sns-example-enable-resource.html](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/sns-example-enable-resource.html)。
+  有关 API 的详细信息，请参阅 *适用于 Ruby 的 AWS SDK API 参考[SetTopicAttributes](https://docs.aws.amazon.com/goto/SdkForRubyV3/sns-2010-03-31/SetTopicAttributes)*中的。

------
#### [ SAP ABAP ]

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

```
    TRY.
        lo_sns->settopicattributes(
            iv_topicarn = iv_topic_arn
            iv_attributename  = iv_attribute_name
            iv_attributevalue = iv_attribute_value ).
        MESSAGE 'Set/updated SNS topic attributes.' TYPE 'I'.
      CATCH /aws1/cx_snsnotfoundexception.
        MESSAGE 'Topic does not exist.' TYPE 'E'.
    ENDTRY.
```
+  有关 API 的详细信息，请参阅适用[SetTopicAttributes](https://docs.aws.amazon.com/sdk-for-sap-abap/v1/api/latest/index.html)于 S *AP 的AWS SDK ABAP API 参考*。

------

# 使用配置传送状态日志 CloudFormation
<a name="msg-status-cloudformation"></a>

要`DeliveryStatusLogging`使用进行配置 CloudFormation，请使用 JSON 或 YAML 模板创建 CloudFormation 堆栈。有关更多信息，请参阅《 CloudFormation 用户指南》中的`AWS::SNS::Topic`资源`DeliveryStatusLogging`属性。以下是 JSON 和 YAML CloudFormation 模板的示例，这些模板用于创建新主题或使用 Amazon SQS `DeliveryStatusLogging` 协议的所有属性更新现有主题。

确保中引用的 IAM 角色`SuccessFeedbackRoleArn`并`FailureFeedbackRoleArn`具有所需的 CloudWatch 日志权限。

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

```
"Resources": {
    "MySNSTopic" : {
        "Type" : "AWS::SNS::Topic",
        "Properties" : {
            "TopicName" : "TestTopic",
            "DisplayName" : "TEST",
            "SignatureVersion" : "2",
            "DeliveryStatusLogging" : [{
                "Protocol": "sqs",
                "SuccessFeedbackSampleRate": "45",
                "SuccessFeedbackRoleArn": "arn:aws:iam::123456789012:role/SNSSuccessFeedback_test1",
                "FailureFeedbackRoleArn": "arn:aws:iam::123456789012:role/SNSFailureFeedback_test2"
            }]
        }
    }
}
```

------
#### [ YAML ]

```
Resources:
  MySNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName:TestTopic
      DisplayName:TEST
      SignatureVersion:2
      DeliveryStatusLogging:
       - Protocol: sqs
         SuccessFeedbackSampleRate: 45
         SuccessFeedbackRoleArn: arn:aws:iam::123456789012:role/SNSSuccessFeedback_test1
         FailureFeedbackRoleArn: arn:aws:iam::123456789012:role/SNSFailureFeedback_test2
```

------

# Amazon SNS 消息传输重试
<a name="sns-message-delivery-retries"></a>

Amazon SNS 为每个传输协议定义了一个*传输策略*。传输策略定义了在发生服务器端错误时（当承载已订阅终端节点的系统变得不可用时），Amazon SNS 如何重试消息传输。当传输策略用尽时，Amazon SNS 将停止重试传输并丢弃邮件——除非已将死信队列附加到订阅。有关更多信息，请参阅 [Amazon SNS 死信队列](sns-dead-letter-queues.md)。

## 传输协议和策略
<a name="delivery-policies-for-protocols"></a>

**注意**  
HTTP/S, you can't change Amazon SNS-defined delivery policies. Only HTTP/S支持自定义策略除外。请参阅[创建配 HTTP/S 送策略](#creating-delivery-policy)。
Amazon SNS 将抖动应用于传输重试。有关更多信息，请参阅发布在 *AWS 架构博客*上的[指数回退和抖动](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)博客文章。
** HTTP/S 终端节点的总策略重试时间不能超过 3,600 秒。这是一项硬性限制，无法增加**。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sns/latest/dg/sns-message-delivery-retries.html)

¹ 对于 Firehose 协议的节流错误，Amazon SNS 使用与客户托管端点相同的传输策略。

## 传输策略阶段
<a name="delivery-policy-stages"></a>

下图显示了传输策略的各个阶段。

![\[一个 x y 轴图，将时间显示为 x 值，将首次传输尝试显示为 y 值。在 y 轴上，传输策略从即刻重试阶段开始，在 x 轴上依次为回退前阶段、回退阶段和回退后阶段。\]](http://docs.aws.amazon.com/zh_cn/sns/latest/dg/images/sns-delivery-policy-phases.png)


每个传输策略包含四个阶段。

1. **立即重试阶段（无延迟）**– 此阶段在首次传输尝试结束后立即发生。在该阶段中重试之间没有延迟。

1. **前退避阶段** – 此阶段紧随即刻重试阶段。Amazon SNS 使用此阶段进行一系列重试，然后再应用退避函数。此阶段指定重试次数以及它们之间的延迟时间量。

1. **退避阶段**：此阶段通过使用重试-退避函数控制各个重试之间的延迟。此阶段设置了最短延迟时间、最长延迟时间和重试-退避函数，该函数定义了延迟时间从最小值增加到最大值的速度。退避函数可以是算术、指数、几何或线性的。

1. **后退避阶段** – 此阶段在退避阶段之后发生。此阶段指定重试次数以及它们之间的延迟时间量。它是最后一个阶段。

## 创建配 HTTP/S 送策略
<a name="creating-delivery-policy"></a>

**您可以使用分为四个阶段的传输策略定义 Amazon SNS 如何重试向 HTTP/S 终端节点传送消息：*无延迟*、*预退退、退避和后退退*。**此策略可让您覆盖原定的重试设置，并根据您的 HTTP 服务器容量进行自定义。

您可以在**主题**或**订阅**级别将您的 HTTP/S 交付策略定义为 JSON 对象：
+ **主题级政策**-适用于链接到该主题的所有 HTTP/S 订阅。使用 [https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html](https://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html) 或 [https://docs.aws.amazon.com/sns/latest/api/API_SetTopicAttributes.html](https://docs.aws.amazon.com/sns/latest/api/API_SetTopicAttributes.html) API 操作设置此策略。
+ **订阅级策略**：仅适用于特定的订阅。使用 [https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html](https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html) 或 [https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html](https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html) API 操作设置此策略。

或者，您也可以在 CloudFormation 模板中使用该[AWS::SNS::Subscription](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html)资源。

您应该根据 HTTP/S 服务器的容量自定义您的传输策略：
+ **所有订阅都使用一台服务器**-如果主题中的所有 HTTP/S 订阅都使用同一台服务器，请将传送策略设置为主题属性，以确保所有订阅之间的一致性。
+ **不同订阅使用不同服务器**：如果订阅针对不同的服务器，则为每个订阅创建独立的传输策略并根据特定服务器的容量进行定制。

您还可以在请求策略中设置 `Content-Type` 标头，以指定通知的媒体类型。默认情况下，Amazon SNS 会将所有通知发送到内容类型设置为的 HTTP/S 终端节点。`text/plain; charset=UTF-8`但是，您可以使用请求策略中的 [`headerContentType`](#header-content-type) 字段来覆盖此原定设置值。

以下 JSON 对象定义了一个包含四阶段重试的传输策略：

1. **无延迟阶段** – 立即重试 3 次。

1. **前退避阶段**：以 1 秒的间隔重试 2 次。

1. **退避阶段**：以指数延迟方式重试 10 次，延迟时间从 1 秒到 60 秒不等。

1. **后退避阶段**：以固定 60 秒间隔重试 35 次。

在丢弃消息之前，Amazon SNS 总共**尝试传输消息 50 次**。为了保留在所有重试后仍无法传输的消息，可将您的订阅配置为将无法传输的消息移动到死信队列（DLQ）。有关更多信息，请参阅 [Amazon SNS 死信队列](sns-dead-letter-queues.md)。

Amazon SNS 将所有 5XX 错误和 429（发送的请求过多）错误视为可重试错误。这些错误会按照传输策略进行重试。其他所有错误都被视为永久失败，不会进行重试。

**注意**  
此传输策略使用 `maxReceivesPerSecond` 属性将每个订阅的传输流量限流至平均每秒 10 条消息。虽然这种机制有助于防止您的 HTTP/S 端点被高流量所淹没，但它旨在保持平均交付率，并且没有严格的上限。偶尔可能会出现超过指定限制的传输流量峰值，尤其是您的发布速率明显高于节流值时。  
当发布（入站）流量超过传输（出站）速率时，可能导致消息积压和传输延迟增加。为避免此类问题，请确保该`maxReceivesPerSecond`值与 HTTP/S 服务器的容量和工作负载要求一致。

以下传输策略示例将 HTTP/S 通知的默认内容类型覆盖为 `application/json`。

```
{
    "healthyRetryPolicy": {
        "minDelayTarget": 1,
        "maxDelayTarget": 60,
        "numRetries": 50,
        "numNoDelayRetries": 3,
        "numMinDelayRetries": 2,
        "numMaxDelayRetries": 35,
        "backoffFunction": "exponential"
    },
    "throttlePolicy": {
        "maxReceivesPerSecond": 10
    },
    "requestPolicy": {
        "headerContentType": "application/json"
    }
}
```

传输策略包含**重试策略**、**节流策略**和**请求策略**。传输策略中共有 **9 个**属性。


| 策略  | 说明 | 限制 | 
| --- | --- | --- | 
| minDelayTarget | 重试的最短延迟时间。**单位：**秒 | 1 至最长延迟时间**原定设置值：**20 | 
| maxDelayTarget | 重试的最长延迟时间。**单位：**秒 | 最短延迟时间至 3600**原定设置值：**20 | 
| numRetries | 重试总数，包括立即重试、前退避重试、退避重试和后退避重试。 | 0 至 100**原定设置值：**3 | 
| numNoDelayRetries | 要立即完成的重试次数，各个重试之间无延迟。 | 0 或更多**原定设置值：**0 | 
| numMinDelayRetries | 前退避阶段的重试次数，各个重试之间有指定的最短延迟时间。 | 0 或更多**原定设置值：**0 | 
| numMaxDelayRetries | 后退避阶段的重试次数，各个重试之间有最长延迟时间。 | 0 或更多**原定设置值：**0 | 
| backoffFunction | 各个重试之间退避的模型。 |  四个选项之一： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sns/latest/dg/sns-message-delivery-retries.html) **默认：**线性  | 
| maxReceivesPerSecond  | 每个订阅每秒的消息传输最大平均数量。 | 1 或更多**默认：**无节流（对传输速率无限制） | 
| headerContentType  | 发送到 HTTP/S 端点的通知的内容类型。 |  如果未定义请求策略，则内容类型原定设置为 `text/plain; charset=UTF-8`。 当为订阅禁用原始消息传送时（原定设置），或者在主题级别定义传送策略时，支持的标头内容类型为 `application/json` 和 `text/plain`。 为订阅启用原始消息传送时，支持以下内容类型： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/sns/latest/dg/sns-message-delivery-retries.html)  | 

Amazon SNS 使用以下公式计算退避阶段的重试次数：

```
numRetries - numNoDelayRetries - numMinDelayRetries - numMaxDelayRetries
```

您可以使用三个参数来控制退避阶段的重试频率。
+ **`minDelayTarget`** – 设置退避阶段第一次重试的延迟时间。
+ **`maxDelayTarget`** – 设置退避阶段最后一次重试的延迟时间。
+ **`backoffFunction`** – 决定 Amazon SNS 用于计算第一次和最后一次重试之间所有重试延迟的算法。您可以从四个重试退避函数中进行选择。

下图说明了在退避阶段，不同的重试退避函数如何影响各次重试之间的延迟。本示例中使用的传输策略包括以下设置：**总共 10 次重试**，**最小延迟为 5 秒**，**最大延迟为 260 秒**。
+ **纵轴**显示每次重试的延迟（以秒为单位）。
+ **横轴**表示重试序列，从第 1 次重试到第 10 次重试。

![\[该图显示了基于四个退避函数（指数、算术、线性和几何）在 10 次重试中的延迟变化情况。每条彩色曲线代表一种函数的延迟模式：指数：延迟增长最快，最早达到最大延迟。线性：每次重试延迟稳步增加。算术和几何：延迟增加速度适中，比线性陡峭，但比指数增长慢。所有曲线都从接近最小延迟 5 秒的位置开始，到第 10 次重试时接近最大延迟 260 秒。\]](http://docs.aws.amazon.com/zh_cn/sns/latest/dg/images/backoff-graph.png)


# 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完成**” 状态。