

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# Amazon SNS 訊息交付
<a name="message-delivery"></a>

本主題說明 Amazon SNS 如何處理各種案例的訊息傳遞。您將了解原始訊息交付，其中 Amazon SNS 會以原始、未修改的格式將訊息交付至端點。您也將探索如何從 Amazon SNS 主題傳送訊息至不同 中的 Amazon SQS 佇列 AWS 帳戶，以深入了解跨帳戶訊息。

本主題提供將 Amazon SNS 訊息交付至不同 Amazon SQS 佇列或 Lambda 函數的資訊 AWS 區域、跨區域交付的運作方式，以及涉及的考量。

此外，您將了解如何監控和解釋訊息傳遞狀態，這可提供訊息是否成功傳遞或遇到問題的關鍵資訊。在訊息傳遞失敗的情況下，您將了解訊息傳遞重試程序，包括 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 端點的原始訊息交付時，值設為 `x-amz-sns-rawdelivery` 的 HTTP 標頭 `true` 會加入至訊息中，表示該訊息已在沒有 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. 在導覽面板上，選擇 **Topics (主題)**。

1. 在**主題**頁面上，選擇訂閱 Firehose、Amazon SQS 或 HTTP/S 端點的主題。

1. 在 ***MyTopic (我的主題)*** 頁面上，於 **Subscription (訂閱)** 區段內，選擇訂閱並選擇 **Edit (編輯)**。

1. 在 **Edit *EXAMPLE1-23bc-4567-d890-ef12g3hij456* (編輯範例1-23bc-4567-d890-ef12g3hij456)** 頁面上，於 **Details (詳細資訊)** 區段內，選擇 **Enable raw message delivery (啟用原始訊息交付)**。

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 會捨棄具有超過 10 個訊息屬性的訊息，這些屬性導向已啟用原始訊息交付的 Amazon SQS 訂閱，並將它們視為用戶端錯誤。

# 傳送 Amazon SNS 訊息至其他帳戶中的 Amazon SQS 佇列
<a name="sns-send-message-to-sqs-cross-account"></a>

本文件說明如何將通知發佈至其他帳戶中具有一個或多個 Amazon SQS 佇列訂閱的 Amazon SNS 主題。如果主題和佇列在相同帳戶中，您要以相同方式設定主題和佇列 (請參閱[向 Amazon SQS 佇列發出 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. 在導覽面板上，選擇 **Topics (主題)**。

1. 選取主題，然後選擇 **Edit (編輯)**。

1. 在**Edit *MyTopic* (編輯 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 使用者/角色也必須擁有 `sns:subscribe` 才能允許其佇列訂閱。

1. 選擇**儲存變更**。

   擁有帳戶 `111122223333` 的登入資料的使用者可以訂閱 MyTopic。

### 步驟 2： AWS 帳戶 使用 將 Amazon SQS 佇列訂閱新增至另一個 中的主題 AWS 管理主控台
<a name="sns-tutorial-add-sqs-subscription-to-sns-topic-another-account"></a>

開始之前，請確定您有主題和佇列的 ARN 且您已[授予主題可傳送訊息至佇列的許可](subscribe-sqs-queue-to-sns-topic.md#SendMessageToSQS.sqs.permissions)。

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

1. 在導覽面板中選擇 **Queues** (佇列)。

1.  在佇列清單中選擇要訂閱 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 設為 **Pending Confirmation (訂閱確認)**。

若要確認訂閱，具備可讀取佇列中訊息之許可的使用者必須擷取訂閱確認 URL，且訂閱擁有者必須使用訂閱確認 URL 來確認訂閱。直到確認訂閱完成，都不會有發佈至主題的通知傳送至佇列。若要確認訂閱，您可以使用 Amazon SQS 主控台或 `[ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/Query_QueryReceiveMessage.html)` 動作。

**注意**  
讓端點訂閱主題之前，請設定佇列的 `sqs:SendMessage` 許可，以確定佇列可以接收主題的訊息。如需詳細資訊，請參閱[步驟 2：將許可提供給 Amazon SNS 主題，以將訊息傳送至 Amazon SQS 佇列。](subscribe-sqs-queue-to-sns-topic.md#SendMessageToSQS.sqs.permissions)。

### 步驟 1： AWS 帳戶 使用 將 Amazon SQS 佇列訂閱新增至另一個 中的主題 AWS 管理主控台
<a name="sns-tutorial-add-sqs-subscription-to-sns-topic-another-account"></a>

開始之前，請確定您有主題和佇列的 ARN 且您已[授予主題可傳送訊息至佇列的許可](subscribe-sqs-queue-to-sns-topic.md#SendMessageToSQS.sqs.permissions)。

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

1. 在導覽面板上，選擇 **Subscriptions (訂閱)**。

1. 在**訂閱**頁面，選擇**建立訂閱**。

1.  在**建立訂閱**頁面上，於**詳細資訊**區段中，執行以下作業：

   1. 在 **Topic ARN (主題 ARN)** 中，輸入主題的 ARN。

   1. 在 **Protocol** (通訊協定) 中，選擇**Amazon SQS**。

   1. 針對 **Endpoint (端點)**，輸入佇列的 ARN。

   1. 選擇**建立訂閱**。
**注意**  
若要能夠與服務進行通訊，佇列必須擁有 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 必須從佇列擁有者傳遞給訂閱擁有者。訂閱擁有者必須將 URL 輸入到 [Amazon SNS 主控台](https://console.aws.amazon.com/sns/v3/home)。

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 主控台中檢視主題訂閱，您現在將會看到該訂閱 ARN 取代 **Subscription ID** (訂閱 ID) 欄位中的 **Pending Confirmation** (待確認中) 訊息。

## 如何強制訂閱以要求對取消訂閱請求進行身分驗證？
<a name="sns-send-message-to-sqs-cross-account-AuthenticateOnUnsubscribe"></a>

訂閱擁有者必須在訂閱確認時將`AuthenticateOnUnsubscribe` 標記設定為 true。
+ 當佇列擁有者建立訂閱時，`AuthenticateOnUnsubscribe` 將自動設定為 True。
+ 當瀏覽至訂閱確認連結而不進行身分驗證時，無法將 `AuthenticateOnUnsubscribe` 設定為 True。

# 將 Amazon SNS 訊息傳送至不同區域中的 Amazon SQS 佇列或 AWS Lambda 函數
<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 支援下列選擇加入區域：


| 區域名稱 | 區域 | 
| --- | --- | 
|  非洲 (開普敦) 區域  |  af-south-1  | 
|  亞太地區 (香港) 區域  |  ap-east-1  | 
|  亞太區域 (海德拉巴)  |  ap-south-2  | 
|  亞太區域 (雅加達)  |  ap-southeast-3  | 
|  亞太區域 (墨爾本) 區域  |  ap-southeast-4  | 
|  Europe (Milan) Region  |  eu-south-1  | 
|  歐洲 (西班牙) 區域  |  eu-south-2  | 
|  歐洲 (蘇黎世) 區域  |  eu-central-2  | 
|  以色列 (特拉維夫) 區域  |  il-central-1  | 
|  Middle East (Bahrain) Region  |  me-south-1  | 
|  中東 (阿拉伯聯合大公國) 區域  |  me-central-1  | 

如需啟用選擇加入區域的資訊，請參閱《》中的[管理 AWS 區域](https://docs.aws.amazon.com/general/latest/gr/rande-manage.html)*Amazon Web Services 一般參考。*

當您使用 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_tw/sns/latest/dg/sns-cross-region-delivery.html)

  以下的存取政策陳述式範例允許選擇加入區域 (af-south-1) 中的 Amazon SNS 主題遞送至預設啟用區域 (us-east-1) 中的 Amazon SQS 佇列。它在路徑 `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_tw/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 將交付日誌寫入 CloudWatch 的必要 IAM 許可，並說明預設日誌群組命名慣例。這可確保您有正確的設定和存取，以監控和分析 CloudWatch 日誌中的訊息傳遞日誌。

**必要的 IAM 許可**

附加用於交付狀態記錄的 IAM 角色必須包含下列許可，才能讓 Amazon SNS 寫入 CloudWatch Logs。您可以使用具有這些許可的現有角色，或在設定期間建立新的角色。

------
#### [ 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 Logs 主控台中檢視這些日誌的許可。

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

# 使用 設定交付狀態記錄 AWS 管理主控台
<a name="topics-attrib"></a>

本主題說明如何啟用 Amazon SNS 主題的訊息交付狀態記錄，包括設定記錄設定、指派 IAM 角色，以及驗證 CloudWatch Logs 擷取交付日誌以進行監控和故障診斷。

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

1. 在導覽面板上，選擇 **Topics (主題)**。

1. 選取所需的**主題**，然後選擇**編輯**。

1. 展開**交付狀態記錄**區段。

1. 選擇您要啟用記錄的**通訊協定** （例如 HTTP、Lambda、Amazon SQS)。

1. 輸入**成功範例速率**，這是您要接收 CloudWatch Logs 之成功訊息的百分比。

1. 在 **IAM 角色**區段中，您必須設定**成功**和**失敗**記錄的角色：
   + **使用現有的服務角色** – 選取具有 Amazon SNS 將日誌寫入 CloudWatch 所需許可的現有 IAM 角色。
   + **建立新的服務角色** – 選擇**建立新的角色**，在 IAM 主控台中定義成功和失敗交付的 IAM 角色。如需許可詳細資訊，請參閱 [交付狀態記錄的先決條件](topics-attrib-prereq.md)。

1. 選擇**儲存變更**。

   啟用記錄後，您可以檢視和剖析包含訊息傳遞狀態的 CloudWatch Logs。如需使用 CloudWatch 的詳細資訊，請參閱 [CloudWatch 文件](https://aws.amazon.com/documentation/cloudwatch)。

**驗證日誌設定**

1. 登入 CloudWatch Logs 主控台。

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` – 訂閱 AWS 應用程式端點之 Amazon SNS 主題的訊息傳遞狀態成功。
+ `ApplicationSuccessFeedbackSampleRate` – 要針對訂閱 AWS 應用程式端點的 Amazon SNS 主題取樣的成功訊息百分比。
+ `ApplicationFailureFeedbackRoleArn` – 訂閱 AWS 應用程式端點之 Amazon SNS 主題的訊息傳遞狀態失敗。
**注意**  
此外，您可以設定應用程式屬性來直接記錄交付狀態，以推送通知服務。如需詳細資訊，請參閱[使用訊息傳遞狀態的 Amazon SNS 應用程式屬性](https://docs.aws.amazon.com/sns/latest/dg/sns-msg-status.html)。

**Amazon SQS**
+ `SQSSuccessFeedbackRoleArn` – 訂閱 Amazon SQS 端點的 Amazon SNS 主題成功訊息傳遞狀態。 Amazon SQS 
+ `SQSSuccessFeedbackSampleRate` – 訂閱 Amazon SQS 端點的 Amazon SNS 主題範例成功訊息的百分比。 Amazon SQS 
+ `SQSFailureFeedbackRoleArn` – 訂閱 Amazon SQS 端點之 Amazon SNS 主題的訊息傳遞狀態失敗。 Amazon SQS 

平台應用程式端點的日誌會寫入與其他端點相同的 CloudWatch Logs 群組。

**注意**  
 `<ENDPOINT>SuccessFeedbackRoleArn` 和 `<ENDPOINT>FailureFeedbackRoleArn` 屬性是用來提供 Amazon SNS 寫入存取權，以代表您使用 CloudWatch Logs。`<ENDPOINT>SuccessFeedbackSampleRate` 屬性用於指定成功傳送訊息的取樣率百分比 (0-100)。在您設定 `<ENDPOINT>FailureFeedbackRoleArn` 屬性後，則所有傳送失敗的訊息都會產生 CloudWatch Logs。

# 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 ]

**SDK for Java 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) 的 SDK**  
 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 開發人員指南》](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 詳細資訊，請參閱《適用於 Kotlin 的AWS SDK API 參考》[https://sdk.amazonaws.com/kotlin/api/latest/index.html](https://sdk.amazonaws.com/kotlin/api/latest/index.html)中的 *SetTopicAttributes*。

------
#### [ 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 ]

**SDK for Ruby**  
 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)》。
+  如需 API 詳細資訊，請參閱 *適用於 Ruby 的 AWS SDK API 參考*中的 [SetTopicAttributes](https://docs.aws.amazon.com/goto/SdkForRubyV3/sns-2010-03-31/SetTopicAttributes)。

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

**適用於 SAP ABAP 的開發套件**  
 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 詳細資訊，請參閱《適用於 SAP ABAP 的AWS SDK API 參考》**中的 [SetTopicAttributes](https://docs.aws.amazon.com/sdk-for-sap-abap/v1/api/latest/index.html)。

------

# 使用 設定交付狀態記錄 CloudFormation
<a name="msg-status-cloudformation"></a>

若要`DeliveryStatusLogging`使用 設定 CloudFormation，請使用 JSON 或 YAML 範本來建立 CloudFormation 堆疊。如需詳細資訊，請參閱 CloudFormation 《 使用者指南》中的 `AWS::SNS::Topic` 資源的 `DeliveryStatusLogging` 屬性。以下是 JSON 和 YAML 中建立新主題或更新具有 Amazon SQS 通訊協定所有`DeliveryStatusLogging`屬性之現有主題的 CloudFormation 範本範例。

確保 中參考`SuccessFeedbackRoleArn`的 IAM 角色`FailureFeedbackRoleArn`具有所需的 CloudWatch Logs 許可。

------
#### [ 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>

**注意**  
您無法變更 Amazon SNS 定義的傳遞政策，但 HTTP/S 除外。只有 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_tw/sns/latest/dg/sns-message-delivery-retries.html)

1 對於 Firehose 通訊協定的限流錯誤，Amazon SNS 使用與客戶受管端點相同的交付政策。

## 傳遞政策階段
<a name="delivery-policy-stages"></a>

下圖顯示傳遞政策的各個階段。

![\[x y 軸圖顯示時間作為 x 值，初始交付嘗試作為 y 值。交付政策從 y 軸上的立即重試階段開始，接著 x 軸上的預退避階段、退避階段和後退避階段。\]](http://docs.aws.amazon.com/zh_tw/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 個屬性**。


| 政策  | Description | 限制條件 | 
| --- | --- | --- | 
| minDelayTarget | 重試的最小延遲。**單位：**秒 | 1 到最大延遲**預設：**20 | 
| maxDelayTarget | 重試的最大延遲。**單位：**秒 | 最小延遲到 3,600**預設：**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_tw/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_tw/sns/latest/dg/sns-message-delivery-retries.html)  | 

Amazon SNS 會使用下列公式計算輪詢階段中的重試次數：

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

您可以使用三個參數來控制退避階段期間的重試頻率：
+ **`minDelayTarget`** – 設定退避階段中第一次重試嘗試的延遲。
+ **`maxDelayTarget`** – 設定退避階段中最後一次重試嘗試的延遲。
+ **`backoffFunction`** – 決定 Amazon SNS 用來計算第一次和最後一次重試之間所有重試嘗試延遲的演算法。您可以從四個可用的重試退避函數中進行選擇。

下圖說明不同的重試退避函數如何影響退避階段期間重試之間的延遲。用於此範例的交付政策包括下列設定：**10 次重試**、**最短延遲 5 秒**，以及**最長延遲 260 秒**。
+ **垂直軸**會顯示每次重試嘗試的延遲 （以秒為單位）。
+ **水平軸**代表重試序列，範圍從第一次到第十次嘗試。

![\[圖表顯示根據四個退避函數，重試如何延遲 10 次嘗試的進度：指數函數、算術函數、線性函數和幾何函數。每個彩色線代表函數的延遲模式：指數：快速增加，達到最大延遲最快，線性：在每次重試時穩定增加，算術和幾何：顯示中等增加，比線性更陡，但比指數更快。所有行都接近 5 秒的最小延遲，並接近第十次重試的 260 秒最大延遲。\]](http://docs.aws.amazon.com/zh_tw/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)。

**注意**  
Amazon SNS 訂閱和 Amazon SQS 佇列必須位於相同的 AWS 帳戶和區域下。
對於 [FIFO 主題](sns-fifo-topics.md)，您可以使用 Amazon SQS 佇列做為 Amazon SNS 訂閱的無效字母佇列。FIFO 主題訂閱使用 FIFO 佇列，而標準主題訂閱則使用標準佇列。
若要使用加密的 Amazon SQS 佇列做為無效字母佇列，您必須使用具有金鑰政策的自訂 KMS，以授予 Amazon SNS 服務主體對 AWS KMS API 動作的存取權。如需詳細資訊，請參閱本指南中的 [使用伺服器端加密保護 Amazon SNS 資料](sns-server-side-encryption.md) 及 *Amazon Simple Queue Service 開發人員指南*中的[保護 Amazon SQS 資料與使用伺服器端加密 (SSE) 和 AWS KMS](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 會使用線性或指數退避函數來重試失敗的傳遞。對於由 Amazon SQS 或 支援的 AWS 受管端點引起的伺服器端錯誤 AWS Lambda，Amazon SNS 會在 23 天內重試交付最多 100，015 次。

客戶管理的端點 (例如 HTTP、SMTP、SMS 或行動推播) 可能也會導致伺服器端錯誤。Amazon SNS 也會重試傳遞到這些類型的端點。雖然 HTTP 端點支援客戶定義的重試政策，但針對 SMTP、SMS 和行動推播端點，Amazon SNS 會將內部傳遞重設政策設為 6 小時內 50 次。

## 無效字母佇列的運作方式
<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 必須指向與您的 Amazon SNS 訂閱位於相同 和 區域中的 Amazon SQS 佇列。 AWS 帳戶 Amazon SNS 如需詳細資訊，請參閱[設定訂閱的 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>

您可以使用 Amazon CloudWatch 指標來監控與您 Amazon SNS 訂閱相關聯的無效字母佇列。所有 Amazon SQS 佇列都會每隔一分鐘發出 CloudWatch 指標。如需詳細資訊，請參閱《[Amazon Simple Queue Service 開發人員指南》中的適用於 Amazon SQS 的 CloudWatch 指標](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-available-cloudwatch-metrics.html)。 **所有包含無效字母佇列的 Amazon SNS 訂閱也會發出 CloudWatch 指標 如需詳細資訊，請參閱[使用 Amazon CloudWatch 監控 Amazon SNS 主題](sns-monitoring-using-cloudwatch.md)。

若要獲得無效字母佇列中的活動通知，您可以使用 CloudWatch 指標和警示。為`NumberOfMessagesSent`指標設定警示並不合適，因為此指標不會擷取因處理嘗試失敗而傳送到 DLQ 的訊息。反之，請使用 `ApproximateNumberOfMessagesVisible` 指標，該指標會擷取 DLQ 中目前可用的所有訊息，包括因處理失敗而移動的訊息。

**CloudWatch 警示設定範例**

1. 建立指標的 [CloudWatch 警示](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ConsoleAlarms.html)。 `ApproximateNumberOfMessagesVisible`

1. 將警示閾值設定為 **1** （或根據您的期望和 DLQ 流量的其他適當值）。

1. 指定警示關閉時要通知的 Amazon SNS **主題**。此 Amazon SNS 主題可將警示通知傳遞給任何端點類型 (例如電子郵件地址、電話號碼或行動傳呼應用程式)。

您可以使用 CloudWatch Logs 調查導致任何 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. [建立 Amazon SNS 主題](sns-create-topic.md)，命名為 `MyTopic`。

1. [建立 Amazon SQS 佇列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html)，命名為 `MyEndpoint`，用來做為 Amazon SNS 訂閱的端點。

1. (Skip for CloudFormation) [訂閱 主題的佇列](sns-sqs-as-subscriber.md)。

1. [建立另一個 Amazon SQS 佇列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html)，命名為 `MyDeadLetterQueue`，用作 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. 在導覽面板上，選擇 **Subscriptions (訂閱)**。

1. 在 **Subscriptions** (訂閱) 頁面上，選取現有訂閱，然後選擇 **Edit** (編輯)。

1. 在 **Edit *1234a567-bc89-012d-3e45-6fg7h890123i***(編輯 1234a567-bc89-012d-3e45-6fg7h890123i) 頁面上，展開 **Redrive policy (dead-letter queue)** (再驅動政策 (無效字母佇列)) 區段，然後執行下列動作：

   1. 選擇 **Enable** (啟用)。

   1. 指定 Amazon SQS 佇列的 ARN。

1. 選擇**儲存變更**。

   您的訂閱已設為使用無效字母佇列。

## 使用 AWS SDK 設定 Amazon SNS 訂閱的無效字母佇列
<a name="configure-dead-letter-queue-aws-sdk"></a>

執行此範例之前，請確定您已完成[先決條件](#dead-letter-queue-prerequisites)。

若要使用 AWS SDK，您必須使用登入資料進行設定。如需詳細資訊，請參閱 *AWS SDK和工具參考指南*中的[共享的配置和認證文件](https://docs.aws.amazon.com/sdkref/latest/guide/creds-config-files.html)。

以下程式碼範例顯示如何使用 `SetSubscriptionAttributesRedrivePolicy`。

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

**適用於 Java 1.x 的 SDK**  
 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。如需詳細資訊，請參閱[「*AWS Command Line Interface 使用者指南」*](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. 在 **Options** (選項) 頁面上，選擇 **Next** (下一步)。

1. 在 **Review** (檢閱) 頁面上，選擇 **Create** (建立)。

   CloudFormation 開始建立`MyDeadLetterQueue`堆疊，並顯示 **CREATE\$1IN\$1PROGRESS** 狀態。程序完成時， CloudFormation 會顯示 **CREATE\$1COMPLETE** 狀態。