

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

# 搭配 Amazon SQS 使用 Lambda
<a name="with-sqs"></a>

**注意**  
如要將資料傳送到 Lambda 函數以外的目標，或在傳送資料之前讓資料更豐富，請參閱 [Amazon EventBridge Pipes](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes.html)。

您可以使用 Lambda 函數處理 Amazon Simple Queue Service (Amazon SQS) 佇列中的訊息。Lambda [事件來源映射](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/standard-queues.html)既支援[標準佇列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues.html)，也支援[先進先出 (FIFO) 佇列](invocation-eventsourcemapping.md)。您也可以使用佈建模式為 Amazon SQS 事件來源映射配置專用輪詢資源。Lambda 函數和 Amazon SQS 佇列必須位於相同的 中 AWS 區域，雖然它們可以位於[不同的 AWS 帳戶](with-sqs-cross-account-example.md) 中。

處理 Amazon SQS 訊息時，您需要實作部分批次回應邏輯，避免批次中部分訊息處理失敗時，已成功處理的訊息被重新執行。Powertools for 的 [Batch Processor 公用程式](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)可自動處理部分批次回應邏輯、縮短開發時間並改善可靠性，藉此 AWS Lambda 簡化此實作。

**Topics**
+ [

## 了解 Amazon SQS 事件來源映射的輪詢和批次處理行為
](#sqs-polling-behavior)
+ [

## 搭配 Amazon SQS 事件來源映射使用佈建模式
](#sqs-provisioned-mode)
+ [

## 設定 Amazon SQS 事件來源映射的佈建模式
](#sqs-configuring-provisioned-mode)
+ [

## 標準佇列訊息事件範例
](#example-standard-queue-message-event)
+ [

## FIFO 佇列訊息事件範例
](#sample-fifo-queues-message-event)
+ [

# 建立和設定 Amazon SQS 事件來源映射
](services-sqs-configure.md)
+ [

# 設定 SQS 事件來源映射的擴展行為
](services-sqs-scaling.md)
+ [

# 在 Lambda 中處理 SQS 事件來源的錯誤
](services-sqs-errorhandling.md)
+ [

# Amazon SQS 事件來源映射的 Lambda 參數
](services-sqs-parameters.md)
+ [

# 對 Amazon SQS 事件來源使用事件篩選
](with-sqs-filtering.md)
+ [

# 教學課程：搭配 Amazon SQS 使用 Lambda
](with-sqs-example.md)
+ [

# 教學課程：使用跨帳戶 Amazon SQS 佇列做為事件來源
](with-sqs-cross-account-example.md)

## 了解 Amazon SQS 事件來源映射的輪詢和批次處理行為
<a name="sqs-polling-behavior"></a>

使用 Amazon SQS 事件來源映射時，Lambda 會輪詢佇列，並在出現事件時[同步](invocation-sync.md)調用函數。每個事件可以包含佇列中的一批訊息。Lambda 一次接收一個批次的這些事件，並為每個批次調用函數一次。當您的函數成功處理批次時，Lambda 會從佇列中刪除其訊息。

當 Lambda 接收到一個批次時，訊息會留在佇列中，但是在佇列的[可見性逾時](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)期間會變成隱藏。如果您的函數成功處理批次中的全部訊息，Lambda 會從佇列中刪除訊息。根據預設，如果函數在處理批次時遇到錯誤，則該批次中的所有訊息會在可見性逾時時間到了之後再次顯示在佇列中。因此，您的函數程式碼必須能夠多次處理相同的訊息，而不會產生副作用。

**警告**  
Lambda 事件來源映射至少會處理每個事件一次，而且可能會重複處理記錄。為避免與重複事件相關的潛在問題，強烈建議您讓函數程式碼具有等冪性。若要進一步了解，請參閱 AWS 知識中心中的[如何使 Lambda 函數具有等冪性](https://repost.aws/knowledge-center/lambda-function-idempotent)。

若要防止 Lambda 多次處理訊息，您可以設定事件來源映射，在函數回應中包含[批次項目失敗](services-sqs-errorhandling.md#services-sqs-batchfailurereporting)，或者可以使用 [DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html) API 動作，在 Lambda 函數成功處理訊息時從佇列中移除訊息。

如需 Lambda 支援用於 SQS 事件來源映射的組態參數的詳細資訊，請參閱[建立 SQS 事件來源映射](services-sqs-configure.md#events-sqs-eventsource)。

## 搭配 Amazon SQS 事件來源映射使用佈建模式
<a name="sqs-provisioned-mode"></a>

對於您需要微調事件來源映射輸送量的工作負載，可以使用佈建模式。在佈建模式中，可以定義佈建的事件輪詢器數量的下限和上限。這些佈建的事件輪詢器專用於您的事件來源映射，並且可以透過回應性自動擴展處理意外的訊息尖峰。使用佈建模式設定的 Amazon SQS 事件來源映射擴展速度快 3 倍 （每分鐘最多 1，000 個並行調用），並支援比預設 Amazon SQS 事件來源映射功能高 16 倍的並行調用 （最多 20，000 個並行調用）。我們建議您針對具有嚴格效能需求的 Amazon SQS 事件驅動型工作負載使用佈建模式，例如處理市場資料饋送的金融服務公司、提供即時個人化建議的電子商務平台，以及管理即時玩家互動的遊戲公司。使用佈建模式會產生額外費用。如需詳細的定價，請參閱 [AWS Lambda 定價](https://aws.amazon.com/lambda/pricing/)。

佈建模式中的每個事件輪詢器最多可處理每秒 1 MB 的輸送量、最多 10 個並行調用，或每秒最多 10 個 Amazon SQS 輪詢 API 呼叫。事件輪詢器 (MinimumPollers) 數目下限的接受值範圍介於 2 到 200 之間，預設值為 2。事件輪詢器 (MaximumPollers) 數目上限的接受值範圍介於 2 到 2，000 之間，預設值為 200。MaximumPollers 必須大於或等於 MinimumPollers。

### 判斷所需的事件輪詢器
<a name="sqs-determining-event-pollers"></a>

若要預估在 SQS ESM 使用佈建模式時確保最佳訊息處理效能所需的事件輪詢器數量，請為您的應用程式收集下列指標：需要低延遲處理的每秒尖峰 SQS 事件數、平均 SQS 事件承載大小、平均 Lambda 函數持續時間，以及設定的批次大小。

首先，您可以使用下列公式，為您的工作負載預估事件輪詢器支援的每秒 SQS 事件數 (EPS)：

```
EPS per event poller = 
        minimum(
            ceiling(1024 / average event size in KB),
            ceiling(10 / average function duration in seconds) * batch size, 
            min(100, 10 * batch size)
                )
```

然後，您可以使用以下公式計算所需的最低輪詢器數量。此計算可確保您佈建足夠的容量來處理尖峰流量需求。

```
Required event pollers = (Peak number of events per second in Queue) / EPS per event poller
```

假設工作負載的預設批次大小為 10、平均事件大小為 3 KB、平均函數持續時間為 100 毫秒，且需要每秒處理 1，000 個事件。在此案例中，每個事件輪詢器每秒將支援約 100 個事件 (EPS)。因此，您應該將最低輪詢器設定為 10，以充分處理您的尖峰流量需求。如果您的工作負載具有相同的特性，但平均函數持續時間為 1 秒，則每個輪詢器將僅支援 10 個 EPS，要求您設定 100 個最低輪詢器，以低延遲支援每秒 1，000 個事件。

建議使用預設批次大小 10 或更高，以最大限度地提高佈建模式事件輪詢器的效率。較高的批次大小可讓每個輪詢器在每次調用時處理更多事件，以提高輸送量和成本效益。規劃事件輪詢器容量時，請考量潛在的流量峰值，並考慮將 minimumPollers 值稍高於計算的最小值，以提供緩衝區。此外，隨著時間的推移監控工作負載特性，因為訊息大小、函數持續時間或流量模式的變更可能需要調整事件輪詢器組態，以維持最佳效能和成本效益。為了精確規劃容量，我們建議您測試特定工作負載，以判斷每個事件輪詢器可以驅動的實際 EPS。

## 設定 Amazon SQS 事件來源映射的佈建模式
<a name="sqs-configuring-provisioned-mode"></a>

您可以使用主控台或 Lambda API，為 Amazon SQS 事件來源映射設定佈建模式。

**設定現有 Amazon SQS 事件來源映射的佈建模式 （主控台）**

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇具有您要為其設定佈建模式之 Amazon SQS 事件來源映射的函數。

1. 選擇**組態**，然後選擇**觸發條件**。

1. 選擇您要為其設定佈建模式的 Amazon SQS 事件來源映射，然後選擇**編輯**。

1. 在**事件來源映射組態**下，選擇**設定佈建模式**。
   + 針對**最低事件輪詢器**，輸入介於 2 到 200 之間的值。如果您未指定值，Lambda 會選擇預設值 2。
   + 針對**事件輪詢器上限**，輸入介於 2 到 2，000 之間的值。此值必須大於或等於**事件輪詢器下限**值。如果您沒有指定值，則 Lambda 會選擇預設值 200。

1. 選擇**儲存**。

您可以使用 中的 `ProvisionedPollerConfig` 物件，以程式設計方式設定佈建模式`EventSourceMappingConfiguration`。例如，下列 `UpdateEventSourceMapping` CLI 命令會設定 5 `MinimumPollers`的值，以及 100 `MaximumPollers`的值。

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --provisioned-poller-config '{"MinimumPollers": 5, "MaximumPollers": 100}'
```

設定佈建模式後，可以透過監控 `ProvisionedPollers` 指標來觀察工作負載的事件輪詢器使用情況。如需詳細資訊，請參閱事件來源映射指標。

若要停用佈建模式並返回預設 （隨需） 模式，您可以使用下列 `UpdateEventSourceMapping` CLI 命令：

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --provisioned-poller-config '{}'
```

**注意**  
佈建模式無法與最大並行設定搭配使用。使用佈建模式時，您可以透過事件輪詢器的數量上限來控制並行上限。

如需設定佈建模式的詳細資訊，請參閱 [建立和設定 Amazon SQS 事件來源映射](services-sqs-configure.md)。

## 標準佇列訊息事件範例
<a name="example-standard-queue-message-event"></a>

**Example Amazon SQS 訊息事件 (標準佇列)**  

```
{
    "Records": [
        {
            "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
            "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
            "body": "Test message.",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1545082649183",
                "SenderId": "AIDAIENQZJOLO23YVJ4VO",
                "ApproximateFirstReceiveTimestamp": "1545082649185"
            },
            "messageAttributes": {
                "myAttribute": {
                    "stringValue": "myValue", 
                    "stringListValues": [], 
                    "binaryListValues": [], 
                    "dataType": "String"
                }
            },
            "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
            "eventSource": "aws:sqs",
            "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue",
            "awsRegion": "us-east-2"
        },
        {
            "messageId": "2e1424d4-f796-459a-8184-9c92662be6da",
            "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...",
            "body": "Test message.",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1545082650636",
                "SenderId": "AIDAIENQZJOLO23YVJ4VO",
                "ApproximateFirstReceiveTimestamp": "1545082650649"
            },
            "messageAttributes": {},
            "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
            "eventSource": "aws:sqs",
            "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue",
            "awsRegion": "us-east-2"
        }
    ]
}
```

依預設，Lambda 會一次輪詢佇列中最多 10 則訊息，並將該批次傳送給函數。為避免調用具有少量記錄的函數，您可設定批次間隔，讓事件來源緩衝記錄最長達五分鐘。調用函數之前，Lambda 會繼續從標準佇列輪詢訊息，直至批次間隔到期、達到[調用承載大小配額](gettingstarted-limits.md)，或達到設定的批次大小上限為止。

如果您使用的是批次時間範圍，並且您的 SQS 佇列包含非常低的流量，Lambda 可能會等到 20 秒，然後再調用您的函數。即使您將批次時間範圍設定為低於 20 秒也是如此。

**注意**  
在 Java 中，還原序列化 JSON 時可能會遇到 null 指標錯誤。這可能是由於 JSON 物件映射器對「Records」和「eventSourceARN」案例轉換的方式所致。

## FIFO 佇列訊息事件範例
<a name="sample-fifo-queues-message-event"></a>

對於 FIFO 佇列，記錄包含與重複資料刪除和定序相關的其他屬性。

**Example Amazon SQS 訊息事件 (FIFO 佇列)**  

```
{
    "Records": [
        {
            "messageId": "11d6ee51-4cc7-4302-9e22-7cd8afdaadf5",
            "receiptHandle": "AQEBBX8nesZEXmkhsmZeyIE8iQAMig7qw...",
            "body": "Test message.",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1573251510774",
                "SequenceNumber": "18849496460467696128",
                "MessageGroupId": "1",
                "SenderId": "AIDAIO23YVJENQZJOL4VO",
                "MessageDeduplicationId": "1",
                "ApproximateFirstReceiveTimestamp": "1573251510774"
            },
            "messageAttributes": {},
            "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
            "eventSource": "aws:sqs",
            "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:fifo.fifo",
            "awsRegion": "us-east-2"
        }
    ]
}
```

# 建立和設定 Amazon SQS 事件來源映射
<a name="services-sqs-configure"></a>

若要使用 Lambda 處理 Amazon SQS 訊息，請正確設定佇列，然後建立 Lambda 事件來源映射。

**Topics**
+ [

## 配置要搭配 Lambda 使用的佇列
](#events-sqs-queueconfig)
+ [

## 設定 Lambda 執行角色許可
](#events-sqs-permissions)
+ [

## 建立 SQS 事件來源映射
](#events-sqs-eventsource)

## 配置要搭配 Lambda 使用的佇列
<a name="events-sqs-queueconfig"></a>

如果您還沒有建立 Amazon SQS 佇列，請[建立一個](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-create-queue.html)來做為 Lambda 函數的事件來源。Lambda 函數和 Amazon SQS 佇列必須位於相同的 中 AWS 區域，雖然它們可以位於[不同的 AWS 帳戶](with-sqs-cross-account-example.md) 中。

為讓您的函數有時間處理每個記錄批次，請將來源佇列的[可見性逾時](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)設定為[函數設定之逾時](configuration-timeout.md)的至少六倍。萬一您的函數在處理前一個批次時遭到調節，額外的時間可允許 Lambda 重試。

**注意**  
函式的逾時必須小於或等於佇列的可見性逾時。當您建立或更新事件來源映射時，Lambda 會驗證此項要求，在函式逾時超過佇列的可見性逾時之時傳回錯誤。

根據預設，只要 Lambda 在處理批次的過程中遇到錯誤，則該批次中的所有訊息都會傳回佇列。在[可見性逾時](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)時間到了之後，這些訊息會再次對 Lambda 可見。您可以將事件來源映射設定為使用[部分批次回應](services-sqs-errorhandling.md#services-sqs-batchfailurereporting)，從而僅將失敗的訊息傳回佇列。此外，如果函數多次處理訊息失敗，Amazon SQS 可將訊息傳送到[無效字母佇列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html)。我們建議將來源佇列的[再驅動政策](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html#policies-for-dead-letter-queues) 的 `maxReceiveCount` 設定為 5 或更大。這讓 Lambda 在將失敗的訊息傳送到無效字母佇列之前，有機會重試幾次。

## 設定 Lambda 執行角色許可
<a name="events-sqs-permissions"></a>

[ AWSLambdaSQSQueueExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaSQSQueueExecutionRole.html) AWS 受管政策包含 Lambda 從 Amazon SQS 佇列讀取所需的許可。您可以將此受管政策新增至函數的[執行角色](lambda-intro-execution-role.md)。

或者，如果您使用的是加密佇列，也需要將下列許可新增至您的執行角色：
+ [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html)

## 建立 SQS 事件來源映射
<a name="events-sqs-eventsource"></a>

建立事件來源映射，指示 Lambda 從您的佇列傳送項目至 Lambda 函數。您可以建立多個事件來源映射，使用單一函數處理來自多個佇列的項目。當 Lambda 調用目標函數時，事件可能包含多個項目，最多為可設定的最大*批次大小*。

若要將函數設定為從 Amazon SQS 讀取，請將 [ AWSLambdaSQSQueueExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaSQSQueueExecutionRole.html) AWS 受管政策連接至您的執行角色。然後，透過以下步驟從主控台建立 **SQS** 事件來源映射。

**若要新增許可並建立觸發條件**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇函數的名稱。

1. 依序選擇 **Configuration** (組態) 索引標籤和 **Permissions** (許可)。

1. 在**角色名稱**下面，選擇執行角色連結。此連結會在 IAM 主控台中開啟該角色。  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/execution-role.png)

1. 選擇**新增許可**，然後選擇**連接政策**。  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/attach-policies.png)

1. 在搜尋欄位中輸入 `AWSLambdaSQSQueueExecutionRole`。將此政策新增至您的執行角色。這是 AWS 受管政策，其中包含函數從 Amazon SQS 佇列讀取所需的許可。如需此政策的詳細資訊，請參閱《AWS 受管政策參考》**中的 [AWSLambdaSQSQueueExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaSQSQueueExecutionRole.html) 一節。

1. 在 Lambda 主控台中返回您的 Lambda 函數。在**函數概觀**下，選擇**新增觸發條件**。  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/add-trigger.png)

1. 選擇觸發條件類型。

1. 設定需要的選項，然後選擇**新增**。

Lambda 支援 Amazon SQS 事件來源的下列組態選項：

**SQS 佇列**  
要從中讀取記錄的 Amazon SQS 佇列。Lambda 函數和 Amazon SQS 佇列必須位於相同的 中 AWS 區域，雖然它們可以位於[不同的 AWS 帳戶](with-sqs-cross-account-example.md) 中。

**啟用觸發條件**  
事件來源映射的狀態。系統會預設選取**啟用觸發條件**。

**批次大小**  
每個批次中要傳送至函數的記錄數量上限。若是標準佇列，這最高可達 10,000 個記錄。若是 FIFO 佇列，最大值為 10。批次大小若超過 10，您還必須將批次間隔 (`MaximumBatchingWindowInSeconds`) 設定為至少 1 秒。  
設定[函數逾時](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/configurations#timeouts)以允許足夠時間來處理整個項目批次。如果項目需要長時間處理，請選擇較小的批次大小。大型批次大小可提升效率，適用非常快速或開銷龐大的工作負載。如果您在函數上設定[保留並行](configuration-concurrency.md)，應最少設定五個並行執行，藉此降低 Lambda 調用函數時的調節錯誤機率。  
Lambda 會將批次中所有記錄以單一呼叫傳送至函數，前提是事件的總大小不超過同步調用的[調用承載大小配額](gettingstarted-limits.md) (6 MB)。Lambda 和 Amazon SQS 兩者均會產生每筆記錄的中繼資料。這個額外的中繼資料會計入總酬載大小，並且可能會導致批次中傳送的記錄總數低於您設定的批次大小。Amazon SQS 傳送的中繼資料欄位長度可能有所不同。如需 Amazon SQS 中繼資料欄位的詳細資訊，請參閱 *Amazon Simple Queue Service API 參考*中的 [ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html) API 操作文件。

**批次視窗**  
調用函式前收集記錄的最長時間 (單位為秒)。這僅適用於標準佇列。  
如果您使用的批次間隔大於 0 秒，則必須考慮佇列[可見性逾時](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)中增加的處理時間。我們建議將您的佇列可見性逾時設定為[函數逾時](configuration-timeout.md)的六倍，再加上 `MaximumBatchingWindowInSeconds` 的值。這可讓您的 Lambda 函數有時間處理每個事件批次，並在發生節流錯誤時重試。  
當訊息可供使用，Lambda 會開始批次處理訊息。Lambda 會開始一次處理五個批次，而函數有五個並行調用。如果訊息仍然可用，Lambda 每分鐘會為您的函數新增最多 300 個並行調用，最多 1，250 個並行調用。使用佈建模式時，每個事件輪詢器最多可處理每秒 1 MB 的輸送量、最多 10 個並行調用，或每秒最多 10 個 Amazon SQS 輪詢 API 呼叫。Lambda 會在設定的最小值和最大值之間擴展事件輪詢器的數量，快速新增每分鐘最多 1，000 個並行調用，以提供 Amazon SQS 事件的低延遲處理。您可以透過這些最小和最大事件輪詢器設定來控制擴展和並行。若要進一步了解函數擴展和並行，請參閱 [了解 Lambda 函數擴展](lambda-concurrency.md)。  
若要處理更多訊息，您可以最佳化 Lambda 函數以達到更高的輸送量。如需詳細資訊，請參閱[了解 如何使用 Amazon SQS 標準佇列 AWS Lambda 擴展](https://aws.amazon.com/blogs/compute/understanding-how-aws-lambda-scales-when-subscribed-to-amazon-sqs-queues/#:~:text=If there are more messages,messages from the SQS queue.)。

**篩選條件**  
新增篩選條件來控制 Lambda 要傳送哪些事件給函數進行處理。如需詳細資訊，請參閱[控制 Lambda 將哪些事件傳送至您的函數](invocation-eventfiltering.md)。

**並行上限**  
事件來源可以調用的並行函數上限。無法與已啟用佈建模式搭配使用。如需詳細資訊，請參閱[設定 Amazon SQS 事件來源的並行上限](services-sqs-scaling.md#events-sqs-max-concurrency)。

**佈建模式**  
啟用時， 會為您的事件來源映射配置專用輪詢資源。您可以設定事件輪詢器的最小 (2-200) 和最大 (2-2000) 數量。每個事件輪詢器最多可以處理每秒 1 MB 的輸送量、最多 10 個並行調用，或每秒最多 10 個 Amazon SQS 輪詢 API 呼叫。  
注意：您無法同時使用佈建模式和最大並行。啟用佈建模式時，請使用最大輪詢器設定來控制並行。

# 設定 SQS 事件來源映射的擴展行為
<a name="services-sqs-scaling"></a>

您可以透過最大並行設定或啟用佈建模式來控制 Amazon SQS 事件來源映射的擴展行為。這些是互斥選項。

根據預設，Lambda 會根據訊息磁碟區自動擴展事件輪詢器。當您啟用佈建模式時，您可以配置最小和最大數量的專用輪詢資源，這些資源仍然準備好處理預期的流量模式。這可讓您以兩種方式最佳化事件來源映射的效能：
+ 標準模式 （預設）：Lambda 會自動管理擴展，從少量輪詢器開始，並根據工作負載向上或向下擴展。
+ 佈建模式：您可以設定具有最小和最大限制的專用輪詢資源，使擴展速度加快 3 倍，處理容量提高 16 倍。

針對標準佇列，Lambda 會使用[長輪詢](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html#sqs-long-polling)來輪詢佇列，直至其處於作用中狀態。當訊息可用時，Lambda 會開始一次處理五個批次，而函數有五個並行調用。如果訊息仍然可用，Lambda 會增加讀取批次的程序數量，每分鐘最多增加 300 個並行調用。事件來源映射可同時處理的調用數目上限為 1，250。當流量較低時，Lambda 會將處理縮減為五個並行調用，並且可以最佳化為最少 2 個並行調用，以減少 Amazon SQS 呼叫和對應的成本。然而，如果啟用並行上限設定，將無法使用此最佳化。

針對 FIFO 佇列，Lambda 會按照其接收的順序傳送訊息到您的函數。當您傳送訊息到 FIFO 佇列時，您可以指定[訊息群組 ID](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/using-messagegroupid-property.html)。Amazon SQS 可確保相同群組中的訊息依序傳遞至 Lambda。當 Lambda 將訊息讀取到批次時，每個批次可能包含來自多個訊息群組的訊息，但訊息的順序會保持不變。如果您的函數傳回錯誤，函數會先在受影響的訊息上嘗試所有重試，之後 Lambda 才會從相同群組接收到額外訊息。

使用佈建模式時，每個事件輪詢器最多可以處理每秒 1 MB 的輸送量、最多 10 個並行調用，或每秒最多 10 個 Amazon SQS 輪詢 API 呼叫。Lambda 會在您設定的最小值和最大值之間擴展事件輪詢器數量，快速新增高達每分鐘 1，000 個並行，以提供 Amazon SQS 事件的一致、低延遲處理。使用佈建模式會產生額外費用。如需詳細的定價，請參閱 [AWS Lambda 定價](https://aws.amazon.com/lambda/pricing/)。每個事件輪詢器對您的 SQS 佇列使用[長輪詢](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html)，每秒最多 10 個輪詢，這會產生 SQS API 請求成本。如需詳細資訊，請參閱 [Amazon SQS 定價](https://aws.amazon.com/sqs/pricing/ )。您可以透過這些最小和最大事件輪詢器設定來控制擴展和並行，而不是使用最大並行設定，因為這些選項無法一起使用。

**注意**  
您無法同時使用最大並行設定和佈建模式。啟用佈建模式時，您可以透過事件輪詢器的最小和最大數量來控制 Amazon SQS 事件來源映射的擴展和並行。

## 設定 Amazon SQS 事件來源的並行上限
<a name="events-sqs-max-concurrency"></a>

您可以使用最大並行設定來控制 SQS 事件來源的擴展行為。請注意，最大並行不能在已啟用佈建模式的情況下使用。並行上限設定限制了 Amazon SQS 事件來源可以調用的函數並行執行個體數。並行上限是事件來源層級的設定。如果您將多個 Amazon SQS 事件來源映射到一個函數，那麼每個事件來源都可以有個別的並行上限設定。您可以使用並行上限來防止一個佇列用完函數的所有[預留並行配額](configuration-concurrency.md)，或其餘的[帳戶並行配額](gettingstarted-limits.md)。對 Amazon SQS 事件來源設定並行無需付費。

重要的是，並行上限和預留並行是兩項獨立的設定。請勿將並行上限設為超過函數的預留並行。若您設定了並行上限，請確定函數的預留並行大於或等於函數上所有 Amazon SQS 事件來源的總並行上限。若小於此上限，Lambda 可能會限流您的訊息。

當您帳戶的並行配額設定為預設值 1,000 時，除非您指定最大並行，否則 Amazon SQS 事件來源映射最高可以擴展至調用數量為該值的函數執行個體。

即便帳戶的預設並行配額增加，Lambda 也可能無法調用數量為新配額的並行函數執行個體。根據預設，對於一個 Amazon SQS 事件來源映射，Lambda 可以擴展為調用最多 1,250 個並行函數執行個體。如果這不足以滿足您的使用案例，請聯絡 AWS 支援，以討論增加您帳戶的 Amazon SQS 事件來源映射並行。

**注意**  
對於 FIFO 佇列，並行調用的上限是[訊息群組 ID](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/using-messagegroupid-property.html) (`messageGroupId`) 的數量或最大並行設定 (以較低者為準)。例如，如果您有六個訊息群組 ID，而最大並行設定為 10，則函數最多可以有六個並行調用。

您可以對新的和現有的 Amazon SQS 事件來源映射設定並行上限。

**使用 Lambda 主控台設定並行上限**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇函數的名稱。

1. 在**函數概觀**下，選擇 **SQS**。這會開啟 **Configuration** (組態) 索引標籤。

1. 選取 Amazon SQS 觸發條件，然後選擇**編輯**。

1. **Maximum concurrency** (並行上限) 請輸入介於 2 到 1,000 之間的數字。若要關閉並行上限，請將方塊保留空白。

1. 選擇**儲存**。

**使用 AWS Command Line Interface (AWS CLI) 設定並行上限**  
使用 [update-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) 命令和 `--scaling-config` 選項。範例：

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --scaling-config '{"MaximumConcurrency":5}'
```

若要關閉並行上限，請為 `--scaling-config` 輸入空值：

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --scaling-config "{}"
```

**使用 Lambda API 設定並行上限**  
使用 [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) 或[UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) 動作搭配 [ScalingConfig](https://docs.aws.amazon.com/lambda/latest/api/API_ScalingConfig.html) 物件。

# 在 Lambda 中處理 SQS 事件來源的錯誤
<a name="services-sqs-errorhandling"></a>

為了處理與 SQS 事件來源相關的錯誤，Lambda 會自動使用重試策略搭配退避策略。您也可以透過設定 SQS 事件來源映射，來自訂錯誤處理行為，以傳回[部分批次回應](#services-sqs-batchfailurereporting)。

## 失敗調用的輪詢策略
<a name="services-sqs-backoff-strategy"></a>

當調用失敗，Lambda 會在實作輪詢策略時嘗試重試調用。根據 Lambda 是否因函數程式碼錯誤或限流而發生失敗，輪詢策略會略有不同。
+  如果是**函數程式碼**導致錯誤，則 Lambda 會停止處理並重試調用。同時，Lambda 會逐漸退避，減少分配給 Amazon SQS 事件來源映射的並行數量。在佇列的可見性逾時時間到了之後，訊息會再次重新出現在佇列中。
+ 如果是**限流**導致調用失敗，Lambda 會減少分配給 Amazon SQS 事件來源映射的並行數量，逐漸重試輪詢。Lambda 會持續重試訊息，直到訊息的時間戳記超過佇列的可見性逾時為止，此時 Lambda 會捨棄訊息。

## 實作部分批次回應
<a name="services-sqs-batchfailurereporting"></a>

當 Lambda 函數在處理批次時遇到錯誤，根據預設，該批次中的所有訊息會再次顯示在佇列中，包含 Lambda 已順利處理的訊息。因此，您的函數可能最後會處理數次相同的訊息。

若要避免重新處理失敗批次中成功處理過的訊息，您可以設定事件來源映射，僅讓失敗的訊息再次可見。我們將其稱為部分批次回應。若要開啟部分批次回應，請在設定事件來源映射時為 [FunctionResponseTypes](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html#lambda-UpdateEventSourceMapping-request-FunctionResponseTypes) 動作指定 `ReportBatchItemFailures`。這可以讓您的函數傳回部分成功，有助於減少記錄上不必要的重試次數。

**注意**  
適用於 的 Powertools [批次處理器公用程式](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)會自動 AWS Lambda 處理所有部分批次回應邏輯。此公用程式簡化了批次處理模式的實作流程，也減少了正確處理批次項目失敗所需的自訂程式碼。該工具組支援 Python、Java、Typescript 與 .NET。

啟動 `ReportBatchItemFailures` 時，Lambda 不會在函數調用失敗時[縮減訊息輪詢的規模](#services-sqs-backoff-strategy)。如果您預期部分訊息會失敗，且不希望這些失敗影響到訊息的處理速度，則請使用 `ReportBatchItemFailures`。

**注意**  
使用部分批次回應時，請注意下列事項：  
如果函數擲出例外情況，便會將整個批次視為完全失敗。
如果您將此功能與 FIFO 佇列一起使用，您的函數應該在第一次失敗後停止處理訊息，並傳回 `batchItemFailures` 中所有失敗與尚未處理的訊息。這有助於保留佇列中訊息的順序。

**若要啟動部分批次報告**

1. 檢閱[實作部分批次回應的最佳實務](https://docs.aws.amazon.com/prescriptive-guidance/latest/lambda-event-filtering-partial-batch-responses-for-sqs/best-practices-partial-batch-responses.html)。

1. 執行以下命令以便為函數啟用 `ReportBatchItemFailures`。若要擷取事件來源映射的 UUID，請執行 [list-event-source-mappings](https://docs.aws.amazon.com/cli/latest/reference/lambda/list-event-source-mappings.html) AWS CLI 命令。

   ```
   aws lambda update-event-source-mapping \
   --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
   --function-response-types "ReportBatchItemFailures"
   ```

1. 更新函數程式碼以擷取所有例外狀況，並傳回 `batchItemFailures` JSON 回應中的失敗訊息。`batchItemFailures` 回應必須含有以 `itemIdentifier` JSON 值表示的訊息 ID 清單。

   例如，假設您有五則訊息的批次，其中，訊息 ID 分別為 `id1`、`id2`、`id3`、`id4`，以及 `id5`。您的函數已成功處理 `id1`、`id3`，以及 `id5`。若要讓訊息 `id2` 和 `id4` 再次於佇列中可見，您的函數應傳回以下回應：

   ```
   { 
     "batchItemFailures": [ 
           {
               "itemIdentifier": "id2"
           },
           {
               "itemIdentifier": "id4"
           }
       ]
   }
   ```

   以下範例函數程式碼會傳回批次中失敗訊息 ID 的清單：

------
#### [ .NET ]

**適用於 .NET 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)儲存庫中設定和執行。
使用 .NET 搭配 Lambda 報告 SQS 批次項目失敗。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   using Amazon.Lambda.Core;
   using Amazon.Lambda.SQSEvents;
   
   // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
   [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
   namespace sqsSample;
   
   public class Function
   {
       public async Task<SQSBatchResponse> FunctionHandler(SQSEvent evnt, ILambdaContext context)
       {
           List<SQSBatchResponse.BatchItemFailure> batchItemFailures = new List<SQSBatchResponse.BatchItemFailure>();
           foreach(var message in evnt.Records)
           {
               try
               {
                   //process your message
                   await ProcessMessageAsync(message, context);
               }
               catch (System.Exception)
               {
                   //Add failed message identifier to the batchItemFailures list
                   batchItemFailures.Add(new SQSBatchResponse.BatchItemFailure{ItemIdentifier=message.MessageId}); 
               }
           }
           return new SQSBatchResponse(batchItemFailures);
       }
   
       private async Task ProcessMessageAsync(SQSEvent.SQSMessage message, ILambdaContext context)
       {
           if (String.IsNullOrEmpty(message.Body))
           {
               throw new Exception("No Body in SQS Message.");
           }
           context.Logger.LogInformation($"Processed message {message.Body}");
           // TODO: Do interesting work based on the new message
           await Task.CompletedTask;
       }
   }
   ```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)儲存庫中設定和執行。
使用 Go 搭配 Lambda 報告 SQS 批次項目失敗。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   package main
   
   import (
   	"context"
   	"fmt"
   	"github.com/aws/aws-lambda-go/events"
   	"github.com/aws/aws-lambda-go/lambda"
   )
   
   func handler(ctx context.Context, sqsEvent events.SQSEvent) (map[string]interface{}, error) {
   	batchItemFailures := []map[string]interface{}{}
   
   	for _, message := range sqsEvent.Records {
   		if len(message.Body) > 0 {
   			// Your message processing condition here
   			fmt.Printf("Successfully processed message: %s\n", message.Body)
   		} else {
   			// Message processing failed
   			fmt.Printf("Failed to process message %s\n", message.MessageId)
   			batchItemFailures = append(batchItemFailures, map[string]interface{}{"itemIdentifier": message.MessageId})
   		}
   	}
   
   	sqsBatchResponse := map[string]interface{}{
   		"batchItemFailures": batchItemFailures,
   	}
   	return sqsBatchResponse, nil
   }
   
   func main() {
   	lambda.Start(handler)
   }
   ```

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

**SDK for Java 2.x**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)儲存庫中設定和執行。
使用 Java 搭配 Lambda 報告 SQS 批次項目失敗。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   import com.amazonaws.services.lambda.runtime.Context;
   import com.amazonaws.services.lambda.runtime.RequestHandler;
   import com.amazonaws.services.lambda.runtime.events.SQSEvent;
   import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse;
    
   import java.util.ArrayList;
   import java.util.List;
    
   public class ProcessSQSMessageBatch implements RequestHandler<SQSEvent, SQSBatchResponse> {
       @Override
       public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) {
            List<SQSBatchResponse.BatchItemFailure> batchItemFailures = new ArrayList<SQSBatchResponse.BatchItemFailure>();
   
            for (SQSEvent.SQSMessage message : sqsEvent.getRecords()) {
                try {
                    //process your message
                } catch (Exception e) {
                    //Add failed message identifier to the batchItemFailures list
                    batchItemFailures.add(new SQSBatchResponse.BatchItemFailure(message.getMessageId()));
                }
            }
            return new SQSBatchResponse(batchItemFailures);
        }
   }
   ```

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

**適用於 JavaScript (v3) 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)儲存庫中設定和執行。
使用 JavaScript 搭配 Lambda 報告 SQS 批次項目失敗。  

   ```
   // Node.js 20.x Lambda runtime, AWS SDK for Javascript V3
   export const handler = async (event, context) => {
       const batchItemFailures = [];
       for (const record of event.Records) {
           try {
               await processMessageAsync(record, context);
           } catch (error) {
               batchItemFailures.push({ itemIdentifier: record.messageId });
           }
       }
       return { batchItemFailures };
   };
   
   async function processMessageAsync(record, context) {
       if (record.body && record.body.includes("error")) {
           throw new Error("There is an error in the SQS Message.");
       }
       console.log(`Processed message: ${record.body}`);
   }
   ```
使用 TypeScript 搭配 Lambda 報告 SQS 批次項目失敗。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   import { SQSEvent, SQSBatchResponse, Context, SQSBatchItemFailure, SQSRecord } from 'aws-lambda';
   
   export const handler = async (event: SQSEvent, context: Context): Promise<SQSBatchResponse> => {
       const batchItemFailures: SQSBatchItemFailure[] = [];
   
       for (const record of event.Records) {
           try {
               await processMessageAsync(record);
           } catch (error) {
               batchItemFailures.push({ itemIdentifier: record.messageId });
           }
       }
   
       return {batchItemFailures: batchItemFailures};
   };
   
   async function processMessageAsync(record: SQSRecord): Promise<void> {
       if (record.body && record.body.includes("error")) {
           throw new Error('There is an error in the SQS Message.');
       }
       console.log(`Processed message ${record.body}`);
   }
   ```

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

**適用於 PHP 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)儲存庫中設定和執行。
使用 PHP 搭配 Lambda 報告 SQS 批次項目失敗。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   <?php
   
   use Bref\Context\Context;
   use Bref\Event\Sqs\SqsEvent;
   use Bref\Event\Sqs\SqsHandler;
   use Bref\Logger\StderrLogger;
   
   require __DIR__ . '/vendor/autoload.php';
   
   class Handler extends SqsHandler
   {
       private StderrLogger $logger;
       public function __construct(StderrLogger $logger)
       {
           $this->logger = $logger;
       }
   
       /**
        * @throws JsonException
        * @throws \Bref\Event\InvalidLambdaEvent
        */
       public function handleSqs(SqsEvent $event, Context $context): void
       {
           $this->logger->info("Processing SQS records");
           $records = $event->getRecords();
   
           foreach ($records as $record) {
               try {
                   // Assuming the SQS message is in JSON format
                   $message = json_decode($record->getBody(), true);
                   $this->logger->info(json_encode($message));
                   // TODO: Implement your custom processing logic here
               } catch (Exception $e) {
                   $this->logger->error($e->getMessage());
                   // failed processing the record
                   $this->markAsFailed($record);
               }
           }
           $totalRecords = count($records);
           $this->logger->info("Successfully processed $totalRecords SQS records");
       }
   }
   
   $logger = new StderrLogger();
   return new Handler($logger);
   ```

------
#### [ Python ]

**適用於 Python 的 SDK (Boto3)**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)儲存庫中設定和執行。
使用 Python 搭配 Lambda 報告 SQS 批次項目失敗。  

   ```
   # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   # SPDX-License-Identifier: Apache-2.0
   
   def lambda_handler(event, context):
       if event:
           batch_item_failures = []
           sqs_batch_response = {}
        
           for record in event["Records"]:
               try:
                   print(f"Processed message: {record['body']}")
               except Exception as e:
                   batch_item_failures.append({"itemIdentifier": record['messageId']})
           
           sqs_batch_response["batchItemFailures"] = batch_item_failures
           return sqs_batch_response
   ```

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

**SDK for Ruby**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda-with-batch-item-handling)儲存庫中設定和執行。
使用 Ruby 搭配 Lambda 報告 SQS 批次項目失敗。  

   ```
   # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   # SPDX-License-Identifier: Apache-2.0
   require 'json'
   
   def lambda_handler(event:, context:)
     if event
       batch_item_failures = []
       sqs_batch_response = {}
   
       event["Records"].each do |record|
         begin
           # process message
         rescue StandardError => e
           batch_item_failures << {"itemIdentifier" => record['messageId']}
         end
       end
   
       sqs_batch_response["batchItemFailures"] = batch_item_failures
       return sqs_batch_response
     end
   end
   ```

------
#### [ Rust ]

**適用於 Rust 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)儲存庫中設定和執行。
使用 Rust 搭配 Lambda 報告 SQS 批次項目失敗。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   use aws_lambda_events::{
       event::sqs::{SqsBatchResponse, SqsEvent},
       sqs::{BatchItemFailure, SqsMessage},
   };
   use lambda_runtime::{run, service_fn, Error, LambdaEvent};
   
   async fn process_record(_: &SqsMessage) -> Result<(), Error> {
       Err(Error::from("Error processing message"))
   }
   
   async fn function_handler(event: LambdaEvent<SqsEvent>) -> Result<SqsBatchResponse, Error> {
       let mut batch_item_failures = Vec::new();
       for record in event.payload.records {
           match process_record(&record).await {
               Ok(_) => (),
               Err(_) => batch_item_failures.push(BatchItemFailure {
                   item_identifier: record.message_id.unwrap(),
               }),
           }
       }
   
       Ok(SqsBatchResponse {
           batch_item_failures,
       })
   }
   
   #[tokio::main]
   async fn main() -> Result<(), Error> {
       run(service_fn(function_handler)).await
   }
   ```

------

如果失敗的事件未傳回佇列，請參閱 AWS 知識中心中的[如何疑難排解 Lambda 函數 SQS ReportBatchItemFailures？](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-sqs-report-batch-item-failures/)。

### 成功與失敗條件
<a name="sqs-batchfailurereporting-conditions"></a>

如果您的函數傳回下列任一項目，Lambda 會將批次視為完全成功：
+ 空白 `batchItemFailures` 清單
+ Null `batchItemFailures` 清單
+ 空白 `EventResponse`
+ Null `EventResponse`

如果您的函數傳回下列任一項目，Lambda 會將批次視為完全失敗：
+ 無效的 JSON 回應
+ 空白字串 `itemIdentifier`
+ Null `itemIdentifier`
+ 具有錯誤金鑰名稱的 `itemIdentifier`
+ 具有不存在之訊息 ID 的 `itemIdentifier` 值

### CloudWatch 指標
<a name="sqs-batchfailurereporting-metrics"></a>

若要判斷您的函數是否正確報告批次項目失敗，您可以在 Amazon CloudWatch 中監控 `NumberOfMessagesDeleted` 和 `ApproximateAgeOfOldestMessage` Amazon SQS 指標。
+ `NumberOfMessagesDeleted` 會追蹤從佇列移除的訊息數目。如果下降到 0，表示您的函數回應並未正確傳回失敗訊息。
+ `ApproximateAgeOfOldestMessage` 會追蹤最舊訊息停留在佇列中的時間長度。此指標的急劇增加可能表示您的函數並未正確傳回失敗訊息。

### 使用 Powertools 進行 AWS Lambda 批次處理器
<a name="services-sqs-batchfailurereporting-powertools"></a>

Powertools for 的批次處理器公用程式 AWS Lambda 會自動處理部分批次回應邏輯，降低實作批次失敗報告的複雜性。以下是使用批次處理器的範例：

**Python**  
如需完整的範例和設定說明，請參閱 [batch processor documentation](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)。
使用 AWS Lambda 批次處理器處理 Amazon SQS 訊息。  

```
import json
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.batch import BatchProcessor, EventType, process_partial_response
from aws_lambda_powertools.utilities.data_classes import SQSEvent
from aws_lambda_powertools.utilities.typing import LambdaContext

processor = BatchProcessor(event_type=EventType.SQS)
logger = Logger()

def record_handler(record):
    logger.info(record)
    # Your business logic here
    # Raise an exception to mark this record as failed
    
def lambda_handler(event, context: LambdaContext):
    return process_partial_response(
        event=event, 
        record_handler=record_handler, 
        processor=processor,
        context=context
    )
```

**TypeScript**  
如需完整的範例和設定說明，請參閱 [batch processor documentation](https://docs.aws.amazon.com/powertools/typescript/latest/features/batch/)。
使用 AWS Lambda 批次處理器處理 Amazon SQS 訊息。  

```
import { BatchProcessor, EventType, processPartialResponse } from '@aws-lambda-powertools/batch';
import { Logger } from '@aws-lambda-powertools/logger';
import type { SQSEvent, Context } from 'aws-lambda';

const processor = new BatchProcessor(EventType.SQS);
const logger = new Logger();

const recordHandler = async (record: any): Promise<void> => {
    logger.info('Processing record', { record });
    // Your business logic here
    // Throw an error to mark this record as failed
};

export const handler = async (event: SQSEvent, context: Context) => {
    return processPartialResponse(event, recordHandler, processor, {
        context,
    });
};
```

# Amazon SQS 事件來源映射的 Lambda 參數
<a name="services-sqs-parameters"></a>

所有 Lambda 事件來源類型都會共用相同的 [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) 和 [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) API 操作。但是，只有一些參數適用於 Amazon SQS。


| 參數 | 必要 | 預設 | 備註 | 
| --- | --- | --- | --- | 
|  BatchSize  |  否  |  10  |  對於標準佇列，最大值為 10,000。對於 FIFO 隊列，最大值為 10。  | 
|  已啟用  |  N  |  true  | 無  | 
|  EventSourceArn  |  Y  | N/A |  資料串流或串流消費者的 ARN  | 
|  FunctionName  |  是  | N/A  | 無  | 
|  FilterCriteria  |  N  |  N/A   |  [控制 Lambda 將哪些事件傳送至您的函數](invocation-eventfiltering.md)  | 
|  FunctionResponseTypes  |  N  | N/A  |  若要讓函數報告批次中的特定失敗，請將值 `ReportBatchItemFailures` 包含在 `FunctionResponseTypes` 中。如需詳細資訊，請參閱[實作部分批次回應](services-sqs-errorhandling.md#services-sqs-batchfailurereporting)。  | 
|  MaximumBatchingWindowInSeconds  |  N  |  0  | FIFO 佇列不支援批次間隔 | 
|  ProvisionedPollerConfig  |  N  |  N/A  |  設定 SQS 事件來源映射的專用事件輪詢器數量下限 (2-200) 和上限 (2-2000)。每個輪詢器最多可處理每秒 1 MB 的輸送量和 10 個並行調用。  | 
|  ScalingConfig  |  N  |  N/A   |  [設定 Amazon SQS 事件來源的並行上限](services-sqs-scaling.md#events-sqs-max-concurrency)  | 

# 對 Amazon SQS 事件來源使用事件篩選
<a name="with-sqs-filtering"></a>

您可以使用事件篩選來控制 Lambda 將哪些記錄從串流或佇列中傳送至函數。如需事件篩選運作方式的一般資訊，請參閱[控制 Lambda 將哪些事件傳送至您的函數](invocation-eventfiltering.md)。

本節重點介紹了 Amazon SQS 事件來源的事件篩選。

**注意**  
Amazon SQS 事件來源映射僅支援依據 `body` 鍵進行篩選。

**Topics**
+ [

## Amazon SQS 事件篩選基本概念
](#filtering-SQS)

## Amazon SQS 事件篩選基本概念
<a name="filtering-SQS"></a>

假設您的 Amazon SQS 佇列包含以下 JSON 格式的訊息。

```
{
    "RecordNumber": 1234,
    "TimeStamp": "yyyy-mm-ddThh:mm:ss",
    "RequestCode": "AAAA"
}
```

此佇列的範例記錄如下所示。

```
{
    "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
    "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
    "body": "{\n "RecordNumber": 1234,\n "TimeStamp": "yyyy-mm-ddThh:mm:ss",\n "RequestCode": "AAAA"\n}",
    "attributes": {
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1545082649183",
        "SenderId": "AIDAIENQZJOLO23YVJ4VO",
        "ApproximateFirstReceiveTimestamp": "1545082649185"
        },
    "messageAttributes": {},
    "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
    "eventSource": "aws:sqs",
    "eventSourceARN": "arn:aws:sqs:us-west-2:123456789012:my-queue",
    "awsRegion": "us-west-2"
}
```

若要根據 Amazon SQS 訊息的內容進行篩選，請使用 Amazon SQS 訊息記錄中的 `body` 金鑰。假設您只想處理 Amazon SQS 訊息中的 `RequestCode` 為 "BBBB" 的記錄。`FilterCriteria` 物件如下所示。

```
{
    "Filters": [
        {
            "Pattern": "{ \"body\" : { \"RequestCode\" : [ \"BBBB\" ] } }"
        }
    ]
}
```

補充說明，此處是篩選條件的 `Pattern` 在純文字 JSON 中擴展的值。

```
{
    "body": {
        "RequestCode": [ "BBBB" ]
        }
}
```

您可以使用主控台、AWS CLI 或 AWS SAM 範本新增篩選條件。

------
#### [ Console ]

若要使用主控台新增此篩選條件，請遵循 [將篩選條件標準連接至事件來源映射 (主控台)](invocation-eventfiltering.md#filtering-console) 中的指示，並針對**篩選條件標準**輸入下列字串。

```
{ "body" : { "RequestCode" : [ "BBBB" ] } }
```

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

若要使用 AWS Command Line Interface (AWS CLI) 來建立具有這些篩選條件標準的新事件來源映射，請執行下列命令。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:sqs:us-east-2:123456789012:my-queue \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"body\" : { \"RequestCode\" : [ \"BBBB\" ] } }"}]}'
```

若要將這些篩選條件標準新增到現有事件來源映射，請執行下列命令。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"body\" : { \"RequestCode\" : [ \"BBBB\" ] } }"}]}'
```

------
#### [ AWS SAM ]

若要使用 AWS SAM 新增此篩選條件，請將下列程式碼片段新增到事件來源的 YAML 範本。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "body" : { "RequestCode" : [ "BBBB" ] } }'
```

------

假設您希望函數僅處理 `RecordNumber` 大於 9999 的記錄。`FilterCriteria` 物件如下所示。

```
{
    "Filters": [
        {
            "Pattern": "{ \"body\" : { \"RecordNumber\" : [ { \"numeric\": [ \">\", 9999 ] } ] } }"
        }
    ]
}
```

補充說明，此處是篩選條件的 `Pattern` 在純文字 JSON 中擴展的值。

```
{
    "body": {
        "RecordNumber": [
            {
                "numeric": [ ">", 9999 ]
            }
        ]
    }
}
```

您可以使用主控台、AWS CLI 或 AWS SAM 範本新增篩選條件。

------
#### [ Console ]

若要使用主控台新增此篩選條件，請遵循 [將篩選條件標準連接至事件來源映射 (主控台)](invocation-eventfiltering.md#filtering-console) 中的指示，並針對**篩選條件標準**輸入下列字串。

```
{ "body" : { "RecordNumber" : [ { "numeric": [ ">", 9999 ] } ] } }
```

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

若要使用 AWS Command Line Interface (AWS CLI) 來建立具有這些篩選條件標準的新事件來源映射，請執行下列命令。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:sqs:us-east-2:123456789012:my-queue \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"body\" : { \"RecordNumber\" : [ { \"numeric\": [ \">\", 9999 ] } ] } }"}]}'
```

若要將這些篩選條件標準新增到現有事件來源映射，請執行下列命令。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"body\" : { \"RecordNumber\" : [ { \"numeric\": [ \">\", 9999 ] } ] } }"}]}'
```

------
#### [ AWS SAM ]

若要使用 AWS SAM 新增此篩選條件，請將下列程式碼片段新增到事件來源的 YAML 範本。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "body" : { "RecordNumber" : [ { "numeric": [ ">", 9999 ] } ] } }'
```

------

針對 Amazon SQS，訊息內文可以是任何字串。但是，如果您的 `FilterCriteria` 預期 `body` 為有效的 JSON 格式，這就會造成問題。反之亦然 — 如果傳入的訊息內文是有效的 JSON 格式，但您的選條件標準預期 `body` 應為純字串，則此可能會導致意外的行為。

為了避免此問題，請確定 `FilterCriteria` 中的內文格式與從佇列收到的訊息中的 `body` 之預期格式相符。篩選訊息之前，Lambda 會自動評估傳入訊息內文之格式和 `body` 的篩選條件模式之格式。如果有不相符的情形，Lambda 就會捨棄訊息。下表摘要說明此評估：


| 傳入訊息 `body` 格式 | 篩選條件模式 `body` 格式 | 產生的動作 | 
| --- | --- | --- | 
|  純文字的字串  |  純文字的字串  |  根據您的篩選條件標準之 Lambda 篩選條件。  | 
|  純文字的字串  |  資料屬性沒有篩選條件模式  |  Lambda 篩選條件 (僅限其他中繼資料屬性) 會根據您的篩選條件標準而定。  | 
|  純文字的字串  |  有效的 JSON  |  Lambda 捨棄訊息。  | 
|  有效的 JSON  |  純文字的字串  |  Lambda 捨棄訊息。  | 
|  有效的 JSON  |  資料屬性沒有篩選條件模式  |  Lambda 篩選條件 (僅限其他中繼資料屬性) 會根據您的篩選條件標準而定。  | 
|  有效的 JSON  |  有效的 JSON  |  根據您的篩選條件標準之 Lambda 篩選條件。  | 

# 教學課程：搭配 Amazon SQS 使用 Lambda
<a name="with-sqs-example"></a>

在本教學課程中，您將建立一個 Lambda 函數，該函數取用 [Amazon Simple Queue Service (Amazon SQS)](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) 佇列中的訊息。只要有新訊息加入佇列，Lambda 函數就會執行。函數會將訊息寫入 Amazon CloudWatch Logs 串流。下圖顯示可用來完成教學課程的 AWS 資源。

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_resources.png)


請執行下列步驟以完成本教學課程：

1. 建立將訊息寫入 CloudWatch Logs 的 Lambda 函數。

1. 建立 Amazon SQS 佇列。

1. 建立 Lambda 事件來源映射。事件來源映射會讀取 Amazon SQS 佇列，並在新增訊息時調用 Lambda 函數。

1. 透過將訊息新增至佇列並監控 CloudWatch Logs 中的結果來測試設定。

## 先決條件
<a name="with-sqs-prepare"></a>

### 安裝 AWS Command Line Interface
<a name="install_aws_cli"></a>

如果您尚未安裝 AWS Command Line Interface，請依照[安裝或更新最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)中的步驟進行安裝。

本教學課程需使用命令列終端機或 Shell 來執行命令。在 Linux 和 macOS 中，使用您偏好的 Shell 和套件管理工具。

**注意**  
在 Windows 中，作業系統的內建終端不支援您常與 Lambda 搭配使用的某些 Bash CLI 命令 (例如 `zip`)。若要取得 Ubuntu 和 Bash 的 Windows 整合版本，請[安裝適用於 Linux 的 Windows 子系統](https://docs.microsoft.com/en-us/windows/wsl/install-win10)。

## 建立執行角色
<a name="with-sqs-create-execution-role"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps1.png)


[執行角色](lambda-intro-execution-role.md)是授予 Lambda 函數存取 AWS 服務 和資源許可的 AWS Identity and Access Management (IAM) 角色。若要允許函數從 Amazon SQS 中讀取項目，請連接 **AWSLambdaSQSQueueExecutionRole** 許可政策。

**建立執行角色並連接 Amazon SQS 許可政策**

1. 開啟 IAM 主控台中的[角色頁面](https://console.aws.amazon.com/iam/home#/roles)。

1. 選擇 **建立角色**。

1. 針對**信任的實體類型**，請選擇 **AWS 服務**。

1. 針對**使用案例**，請選擇 **Lambda**。

1. 選擇**下一步**。

1. 在**許可政策**搜尋方塊中，輸入 **AWSLambdaSQSQueueExecutionRole**。

1. 選取 **AWSLambdaSQSQueueExecutionRole** 政策，然後選擇**下一步**。

1. 針對**角色詳細資訊**下的**角色名稱**，請輸入 **lambda-sqs-role**，然後選擇**建立角色**。

角色建立後，請記下執行角色的 Amazon Resource Name (ARN)。在後續步驟中會需要用到它。

## 建立函數
<a name="with-sqs-create-function"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps2.png)


建立 Lambda 函數，它處理 Amazon SQS 訊息。函數程式碼會將 Amazon SQS 的訊息內文記錄到 Amazon CloudWatch Logs。

本教學課程使用 Node.js 24 執行時間，但我們也提供其他執行時間語言的範例程式碼。您可以在下列方塊中選取索引標籤，查看您感興趣的執行期程式碼。此步驟要使用的 JavaScript 程式碼，位於 **JavaScript** 索引標籤中顯示的第一個範例。

------
#### [ .NET ]

**適用於 .NET 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 .NET 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
﻿using Amazon.Lambda.Core;
using Amazon.Lambda.SQSEvents;


// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace SqsIntegrationSampleCode
{
    public async Task FunctionHandler(SQSEvent evnt, ILambdaContext context)
    {
        foreach (var message in evnt.Records)
        {
            await ProcessMessageAsync(message, context);
        }

        context.Logger.LogInformation("done");
    }

    private async Task ProcessMessageAsync(SQSEvent.SQSMessage message, ILambdaContext context)
    {
        try
        {
            context.Logger.LogInformation($"Processed message {message.Body}");

            // TODO: Do interesting work based on the new message
            await Task.CompletedTask;
        }
        catch (Exception e)
        {
            //You can use Dead Letter Queue to handle failures. By configuring a Lambda DLQ.
            context.Logger.LogError($"An error occurred");
            throw;
        }

    }
}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Go 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package integration_sqs_to_lambda

import (
	"fmt"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

func handler(event events.SQSEvent) error {
	for _, record := range event.Records {
		err := processMessage(record)
		if err != nil {
			return err
		}
	}
	fmt.Println("done")
	return nil
}

func processMessage(record events.SQSMessage) error {
	fmt.Printf("Processed message %s\n", record.Body)
	// TODO: Do interesting work based on the new message
	return nil
}

func main() {
	lambda.Start(handler)
}
```

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

**SDK for Java 2.x**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Java 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;

public class Function implements RequestHandler<SQSEvent, Void> {
    @Override
    public Void handleRequest(SQSEvent sqsEvent, Context context) {
        for (SQSMessage msg : sqsEvent.getRecords()) {
            processMessage(msg, context);
        }
        context.getLogger().log("done");
        return null;
    }

    private void processMessage(SQSMessage msg, Context context) {
        try {
            context.getLogger().log("Processed message " + msg.getBody());

            // TODO: Do interesting work based on the new message

        } catch (Exception e) {
            context.getLogger().log("An error occurred");
            throw e;
        }

    }
}
```

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

**適用於 JavaScript (v3) 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/blob/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 JavaScript 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
exports.handler = async (event, context) => {
  for (const message of event.Records) {
    await processMessageAsync(message);
  }
  console.info("done");
};

async function processMessageAsync(message) {
  try {
    console.log(`Processed message ${message.body}`);
    // TODO: Do interesting work based on the new message
    await Promise.resolve(1); //Placeholder for actual async work
  } catch (err) {
    console.error("An error occurred");
    throw err;
  }
}
```
使用 TypeScript 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { SQSEvent, Context, SQSHandler, SQSRecord } from "aws-lambda";

export const functionHandler: SQSHandler = async (
  event: SQSEvent,
  context: Context
): Promise<void> => {
  for (const message of event.Records) {
    await processMessageAsync(message);
  }
  console.info("done");
};

async function processMessageAsync(message: SQSRecord): Promise<any> {
  try {
    console.log(`Processed message ${message.body}`);
    // TODO: Do interesting work based on the new message
    await Promise.resolve(1); //Placeholder for actual async work
  } catch (err) {
    console.error("An error occurred");
    throw err;
  }
}
```

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

**適用於 PHP 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 PHP 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
<?php

# using bref/bref and bref/logger for simplicity

use Bref\Context\Context;
use Bref\Event\InvalidLambdaEvent;
use Bref\Event\Sqs\SqsEvent;
use Bref\Event\Sqs\SqsHandler;
use Bref\Logger\StderrLogger;

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

class Handler extends SqsHandler
{
    private StderrLogger $logger;
    public function __construct(StderrLogger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @throws InvalidLambdaEvent
     */
    public function handleSqs(SqsEvent $event, Context $context): void
    {
        foreach ($event->getRecords() as $record) {
            $body = $record->getBody();
            // TODO: Do interesting work based on the new message
        }
    }
}

$logger = new StderrLogger();
return new Handler($logger);
```

------
#### [ Python ]

**適用於 Python 的 SDK (Boto3)**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Python 搭配 Lambda 來使用 SQS 事件。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def lambda_handler(event, context):
    for message in event['Records']:
        process_message(message)
    print("done")

def process_message(message):
    try:
        print(f"Processed message {message['body']}")
        # TODO: Do interesting work based on the new message
    except Exception as err:
        print("An error occurred")
        raise err
```

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

**SDK for Ruby**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Ruby 搭配 Lambda 來使用 SQS 事件。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def lambda_handler(event:, context:)
  event['Records'].each do |message|
    process_message(message)
  end
  puts "done"
end

def process_message(message)
  begin
    puts "Processed message #{message['body']}"
    # TODO: Do interesting work based on the new message
  rescue StandardError => err
    puts "An error occurred"
    raise err
  end
end
```

------
#### [ Rust ]

**適用於 Rust 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)儲存庫中設定和執行。
使用 Rust 搭配 Lambda 來使用 SQS 事件。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use aws_lambda_events::event::sqs::SqsEvent;
use lambda_runtime::{run, service_fn, Error, LambdaEvent};

async fn function_handler(event: LambdaEvent<SqsEvent>) -> Result<(), Error> {
    event.payload.records.iter().for_each(|record| {
        // process the record
        tracing::info!("Message body: {}", record.body.as_deref().unwrap_or_default())
    });

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        // disable printing the name of the module in every log line.
        .with_target(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        .init();

    run(service_fn(function_handler)).await
}
```

------

**若要建立 Node.js Lambda 函數**

1. 建立專案的目錄，然後切換至該目錄。

   ```
   mkdir sqs-tutorial
   cd sqs-tutorial
   ```

1. 將範例 JavaScript 程式碼複製到名為 `index.js` 的新檔案。

1. 使用以下 `zip` 命令建立部署套件。

   ```
   zip function.zip index.js
   ```

1. 使用 [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) AWS CLI 命令建立 Lambda 函數。針對 `role` 參數，輸入您之前建立的執行角色 ARN。
**注意**  
該 Lambda 函數和 Amazon SQS 佇列必須位於相同的 AWS 區域。

   ```
   aws lambda create-function --function-name ProcessSQSRecord \
   --zip-file fileb://function.zip --handler index.handler --runtime nodejs24.x \
   --role arn:aws:iam::111122223333:role/lambda-sqs-role
   ```

## 測試函數
<a name="with-sqs-create-test-function"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps3.png)


使用 `invoke` AWS CLI 命令和範例 Amazon SQS 事件手動叫用 Lambda 函數。

**使用範例事件調用 Lambda 函數**

1. 將下面的 JSON 儲存為名為 `input.json` 的檔案。此 JSON 會模擬 Amazon SQS 可能傳送至 Lambda 函數的事件，其中 `"body"` 包含佇列中的實際訊息。在此範例中，訊息為 `"test"`。  
**Example Amazon SQS 事件**  

   這是測試事件，您不需要變更訊息或帳號。

   ```
   {
       "Records": [
           {
               "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
               "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
               "body": "test",
               "attributes": {
                   "ApproximateReceiveCount": "1",
                   "SentTimestamp": "1545082649183",
                   "SenderId": "AIDAIENQZJOLO23YVJ4VO",
                   "ApproximateFirstReceiveTimestamp": "1545082649185"
               },
               "messageAttributes": {},
               "md5OfBody": "098f6bcd4621d373cade4e832627b4f6",
               "eventSource": "aws:sqs",
               "eventSourceARN": "arn:aws:sqs:us-east-1:111122223333:my-queue",
               "awsRegion": "us-east-1"
           }
       ]
   }
   ```

1. 執行下列[叫用](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/invoke.html) AWS CLI 命令。此命令在回應中傳回 CloudWatch 日誌。如需擷取日誌的詳細資訊，請參閱[使用 存取日誌 AWS CLI](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-cli)。

   ```
   aws lambda invoke --function-name ProcessSQSRecord --payload file://input.json out --log-type Tail \
   --query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
   ```

   如果您使用的是第 2 AWS CLI 版，則需要 **cli-binary-format**選項。若要讓此成為預設的設定，請執行 `aws configure set cli-binary-format raw-in-base64-out`。若要取得更多資訊，請參閱*《AWS Command Line Interface 使用者指南第 2 版》*中 [AWS CLI 支援的全域命令列選項](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。

1. 在回應中查找 `INFO` 日誌。這是 Lambda 函數記錄訊息內文的位置。您應該會看到類似以下內容的輸出：

   ```
   2023-09-11T22:45:04.271Z	348529ce-2211-4222-9099-59d07d837b60	INFO	Processed message test
   2023-09-11T22:45:04.288Z	348529ce-2211-4222-9099-59d07d837b60	INFO	done
   ```

## 建立 Amazon SQS 佇列
<a name="with-sqs-configure-sqs"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps4.png)


建立 Lambda 函數可用作事件來源的 Amazon SQS 佇列。該 Lambda 函數和 Amazon SQS 佇列必須位於相同的 AWS 區域。

**建立佇列**

1. 開啟 [Amazon SQS 主控台](https://console.aws.amazon.com/sqs)。

1. 選擇**建立佇列**。

1. 輸入佇列的名稱。將所有其他選項保留為預設值。

1. 選擇**建立佇列**。

建立佇列後，請記下其 ARN。在下個步驟中，將佇列與您的 Lambda 函數建立關聯時會需要用到它。

## 設定事件來源
<a name="with-sqs-attach-notification-configuration"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps5.png)


透過建立[事件來源映射](invocation-eventsourcemapping.md)，將 Amazon SQS 佇列連線至 Lambda 函數。事件來源映射會讀取 Amazon SQS 佇列，並在新增訊息時調用 Lambda 函數。

若要在 Amazon SQS 佇列和 Lambda 函數之間建立映射，請使用 [create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) AWS CLI 命令。範例：

```
aws lambda create-event-source-mapping --function-name ProcessSQSRecord  --batch-size 10 \
--event-source-arn arn:aws:sqs:us-east-1:111122223333:my-queue
```

若要獲取事件來源映射清單，請使用 [list-event-source-mappings](https://awscli.amazonaws.com/v2/documentation/api/2.1.29/reference/lambda/list-event-source-mappings.html) 命令。範例：

```
aws lambda list-event-source-mappings --function-name ProcessSQSRecord
```

## 傳送測試訊息
<a name="with-sqs-test-message"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps6.png)


**將 Amazon SQS 訊息傳送至 Lambda 函數**

1. 開啟 [Amazon SQS 主控台](https://console.aws.amazon.com/sqs)。

1. 選擇您稍早建立的佇列。

1. 選擇**傳送及接收訊息**。

1. 在**訊息內文**下，輸入測試訊息，例如「這是測試訊息」。

1. 選擇**傳送訊息**。

Lambda 輪詢佇列以查看是否有更新。當有新訊息時，Lambda 會使用佇列中的此新事件資料來叫用您的函數。如果函數處理常式傳回而無例外情況，則 Lambda 會認為訊息已成功處理，並開始讀取佇列中的新訊息。成功處理訊息之後，Lambda 從佇列中自動刪除它。如果處理常式擲出例外情況，Lambda 會認為訊息批次未成功處理，並且 Lambda 會調用具有相同訊息批次的函數。

## 檢查 CloudWatch 日誌
<a name="with-sqs-check-logs"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sqs_tut_steps7.png)


**確認函數已處理訊息**

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇 **ProcessSQSRecord** 函數。

1. 選擇**監控**。

1. 選擇**檢視 CloudWatch 日誌**。

1. 在 CloudWatch 主控台中，選擇函數的**日誌串流**。

1. 查找 `INFO` 日誌。這是 Lambda 函數記錄訊息內文的位置。應能看到您從 Amazon SQS 佇列傳送的訊息。範例：

   ```
   2023-09-11T22:49:12.730Z b0c41e9c-0556-5a8b-af83-43e59efeec71 INFO Processed message this is a test message.
   ```

## 清除您的資源
<a name="cleanup"></a>

除非您想要保留為此教學課程建立的資源，否則您現在便可刪除。透過刪除您不再使用 AWS 的資源，您可以避免不必要的 費用 AWS 帳戶。

**刪除執行角色**

1. 開啟 IAM 主控台中的 [角色頁面](https://console.aws.amazon.com/iam/home#/roles) 。

1. 選取您建立的執行角色。

1. 選擇**刪除**。

1. 在文字輸入欄位中輸入角色的名稱，然後選擇 **刪除** 。

**若要刪除 Lambda 函數**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇您建立的函數。

1. 選擇 **Actions** (動作)、**Delete** (刪除)。

1. 在文字輸入欄位中輸入 **confirm**，然後選擇 **刪除** 。

**刪除 Amazon SQS 佇列**

1. 登入 AWS 管理主控台 並開啟位於 https：//[https://console.aws.amazon.com/sqs/](https://console.aws.amazon.com/sqs/) 的 Amazon SQS 主控台。

1. 選取您建立的佇列。

1. 選擇 **刪除** 。

1. 在文字輸入欄位中輸入 **confirm**。

1. 選擇 **刪除** 。

# 教學課程：使用跨帳戶 Amazon SQS 佇列做為事件來源
<a name="with-sqs-cross-account-example"></a>

在本教學課程中，您會建立 Lambda 函數，使用來自不同 AWS 帳戶中 Amazon Simple Queue Service (Amazon SQS) 佇列的訊息。本教學課程涉及兩個 AWS 帳戶：**帳戶 A** 是指包含 Lambda 函數的帳戶，**帳戶 B** 是指包含 Amazon SQS 佇列的帳戶。

## 先決條件
<a name="with-sqs-cross-account-prepare"></a>

### 安裝 AWS Command Line Interface
<a name="install_aws_cli"></a>

如果您尚未安裝 AWS Command Line Interface，請依照[安裝或更新最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)中的步驟進行安裝。

本教學課程需使用命令列終端機或 Shell 來執行命令。在 Linux 和 macOS 中，使用您偏好的 Shell 和套件管理工具。

**注意**  
在 Windows 中，作業系統的內建終端不支援您常與 Lambda 搭配使用的某些 Bash CLI 命令 (例如 `zip`)。若要取得 Ubuntu 和 Bash 的 Windows 整合版本，請[安裝適用於 Linux 的 Windows 子系統](https://docs.microsoft.com/en-us/windows/wsl/install-win10)。

## 建立執行角色 (帳戶 A)
<a name="with-sqs-cross-account-create-execution-role"></a>

在**帳戶 A** 中，建立 [執行角色](lambda-intro-execution-role.md)，授予您的函數存取所需 AWS 資源的許可。

**若要建立執行角色**

1. 在 AWS Identity and Access Management (IAM) 主控台中開啟[角色頁面](https://console.aws.amazon.com/iam/home#/roles)。

1. 選擇建**立角色**。

1. 建立具備下列屬性的角色。
   + **信任實體** – **AWS Lambda**。
   + **許可** - **AWSLambdaSQSQueueExecutionRole**
   + **角色名稱** - **cross-account-lambda-sqs-role**。

**AWSLambdaSQSQueueExecutionRole** 政策具備函數自 Amazon SQS 讀取項目以及寫入日誌到 Amazon CloudWatch Logs 時所需的許可。

## 建立函數 (帳戶 A)
<a name="with-sqs-cross-account-create-function"></a>

在**帳戶 A** 中建立 Lambda 函數，它會處理 Amazon SQS 訊息。該 Lambda 函數和 Amazon SQS 佇列必須位於相同的 AWS 區域。

下列 Node.js 程式碼範例將每則訊息寫入 CloudWatch Logs 的日誌中。

**Example index.mjs**  

```
export const handler = async function(event, context) {
  event.Records.forEach(record => {
    const { body } = record;
    console.log(body);
  });
  return {};
}
```

**建立函數**
**注意**  
遵循這些步驟，建立 Node.js 函式。對於其他語言，步驟類似，但有些細節不同。

1. 將程式碼範例儲存為名為 `index.mjs` 的檔案。

1. 建立部署套件。

   ```
   zip function.zip index.mjs
   ```

1. 使用 `create-function` AWS Command Line Interface (AWS CLI) 命令建立 函數。將 `arn:aws:iam::111122223333:role/cross-account-lambda-sqs-role` 取代為先前建立之執行角色的 ARN。

   ```
   aws lambda create-function --function-name CrossAccountSQSExample \
   --zip-file fileb://function.zip --handler index.handler --runtime nodejs24.x \
   --role arn:aws:iam::111122223333:role/cross-account-lambda-sqs-role
   ```

## 測試函數 (帳戶 A)
<a name="with-sqs-cross-account-create-test-function"></a>

在**帳戶 A** 中，使用 `invoke` AWS CLI 命令和範例 Amazon SQS 事件手動測試 Lambda 函數。

如果處理常式均正常傳回而無例外情況，Lambda 會認為訊息已成功處理，並開始讀取佇列中的新訊息。成功處理訊息之後，Lambda 從佇列中自動刪除它。如果處理常式擲出例外情況，Lambda 會認為訊息批次未成功處理，並且 Lambda 會調用具有相同訊息批次的函數。

1. 將下面的 JSON 儲存為名為 `input.txt` 的檔案。

   ```
   {
       "Records": [
           {
               "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
               "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
               "body": "test",
               "attributes": {
                   "ApproximateReceiveCount": "1",
                   "SentTimestamp": "1545082649183",
                   "SenderId": "AIDAIENQZJOLO23YVJ4VO",
                   "ApproximateFirstReceiveTimestamp": "1545082649185"
               },
               "messageAttributes": {},
               "md5OfBody": "098f6bcd4621d373cade4e832627b4f6",
               "eventSource": "aws:sqs",
               "eventSourceARN": "arn:aws:sqs:us-east-1:111122223333:example-queue",
               "awsRegion": "us-east-1"
           }
       ]
   }
   ```

   上述 JSON 會模擬 Amazon SQS 可能傳送至 Lambda 函數的事件，其中 `"body"` 包含佇列中的實際訊息。

1. 執行下列 `invoke` AWS CLI 命令。

   ```
   aws lambda invoke --function-name CrossAccountSQSExample \
   --cli-binary-format raw-in-base64-out \
   --payload file://input.txt outputfile.txt
   ```

   如果您使用的是第 2 AWS CLI 版，則需要 **cli-binary-format**選項。若要讓此成為預設的設定，請執行 `aws configure set cli-binary-format raw-in-base64-out`。若要取得更多資訊，請參閱*《AWS Command Line Interface 使用者指南第 2 版》*中 [AWS CLI 支援的全域命令列選項](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。

1. 在檔案 `outputfile.txt` 中確認輸出。

## 建立 Amazon SQS 佇列 (帳戶 B)
<a name="with-sqs-cross-account-configure-sqs"></a>

在**帳戶 B** 中，建立**帳戶 A** 中 Lambda 函數可用作事件來源的 Amazon SQS 佇列。該 Lambda 函數和 Amazon SQS 佇列必須位於相同的 AWS 區域。

**建立佇列**

1. 開啟 [Amazon SQS 主控台](https://console.aws.amazon.com/sqs)。

1. 選擇 **建立佇列** 。

1. 建立具備下列屬性的佇列。
   + **Type** (類型) - **Standard** (標準)
   + **Name** (名稱) - **LambdaCrossAccountQueue**
   + **Configuration** (組態) - 保留預設設定。
   + **存取政策** - 選擇**進階**。貼入下列 JSON 政策中。取代以下的值：
     + `111122223333`**帳戶 A** 的 ： AWS 帳戶 ID
     + `444455556666`**帳戶 B** 的 ： AWS 帳戶 ID

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

****  

     ```
     {
         "Version":"2012-10-17",		 	 	 
         "Id": "Queue1_Policy_UUID",
         "Statement": [
             {
                 "Sid": "Queue1_AllActions",
                 "Effect": "Allow",
                 "Principal": {
                     "AWS": [
                         "arn:aws:iam::111122223333:role/cross-account-lambda-sqs-role"
                     ]
                 },
                 "Action": "sqs:*",
                 "Resource": "arn:aws:sqs:us-east-1:444455556666:LambdaCrossAccountQueue"
             }
         ]
     }
     ```

------

     此政策許可**帳戶 A** 中的 Lambda 執行角色取用此 Amazon SQS 佇列中的訊息。

1. 建立佇列後，記錄其 Amazon Resource Name (ARN)。在下個步驟中，將佇列與您的 Lambda 函數建立關聯時會需要用到它。

## 設定事件來源 (帳戶 A)
<a name="with-sqs-cross-account-event-source"></a>

在**帳戶 A** 中，執行下列`create-event-source-mapping` AWS CLI 命令，在**帳戶 B** 中的 Amazon SQS 佇列與 Lambda 函數之間建立事件來源映射。將 `arn:aws:sqs:us-east-1:444455556666:LambdaCrossAccountQueue` 取代為您在上一個步驟中建立的 Amazon SQS 佇列 ARN。

```
aws lambda create-event-source-mapping --function-name CrossAccountSQSExample --batch-size 10 \
--event-source-arn arn:aws:sqs:us-east-1:444455556666:LambdaCrossAccountQueue
```

若要取得事件來源映射的清單，請執行下列命令。

```
aws lambda list-event-source-mappings --function-name CrossAccountSQSExample \
--event-source-arn arn:aws:sqs:us-east-1:444455556666:LambdaCrossAccountQueue
```

## 測試設定
<a name="with-sqs-final-integration-test-no-iam"></a>

現在您可以測試設定，如下所示：

1. 在**帳戶 B** 中，開啟 [Amazon SQS 主控台](https://console.aws.amazon.com/sqs)。

1. 選擇您先前建立的 **LambdaCrossAccountQueue**。

1. 選擇**傳送及接收訊息**。

1. 在 **Message body** (訊息主體) 中，輸入測試訊息。

1. 選擇**傳送訊息**。

**帳戶 A** 中您的 Lambda 函數應該會收到訊息。Lambda 會繼續輪詢佇列是否有更新。當有新訊息時，Lambda 會使用佇列中的此新事件資料來調用您的函數。您的函數會執行並在 Amazon CloudWatch 中建立日誌。可在 [CloudWatch 主控台](https://console.aws.amazon.com/cloudwatch)中檢視日誌。

## 清除您的資源
<a name="cleanup"></a>

除非您想要保留為此教學課程建立的資源，否則您現在便可刪除。透過刪除您不再使用 AWS 的資源，您可以避免不必要的 費用 AWS 帳戶。

在**帳戶 A** 中，清除您的執行角色和 Lambda 函數。

**刪除執行角色**

1. 開啟 IAM 主控台中的 [角色頁面](https://console.aws.amazon.com/iam/home#/roles) 。

1. 選取您建立的執行角色。

1. 選擇**刪除**。

1. 在文字輸入欄位中輸入角色的名稱，然後選擇 **刪除** 。

**若要刪除 Lambda 函數**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇您建立的函數。

1. 選擇 **Actions** (動作)、**Delete** (刪除)。

1. 在文字輸入欄位中輸入 **confirm**，然後選擇 **刪除** 。

在**帳戶 B** 中，清除 Amazon SQS 佇列。

**刪除 Amazon SQS 佇列**

1. 登入 AWS 管理主控台 並開啟位於 https：//[https://console.aws.amazon.com/sqs/](https://console.aws.amazon.com/sqs/) 的 Amazon SQS 主控台。

1. 選取您建立的佇列。

1. 選擇 **刪除** 。

1. 在文字輸入欄位中輸入 **confirm**。

1. 選擇 **刪除** 。