

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

# 使用 Lambda 遞迴迴圈偵測功能防止無限迴圈
<a name="invocation-recursion"></a>

當您將 Lambda 函數設定為輸出至調用該函數的相同服務或資源時，就可以建立無限遞迴迴圈。例如，Lambda 函數可能會將訊息寫入 Amazon Simple Queue Service (Amazon SQS) 佇列，然後調用相同的函數。此調用會導致函數將另一則訊息寫入佇列，進而再次調用函數。

意外的遞迴迴圈可能會導致意外費用向您的 收費 AWS 帳戶。迴圈也可能導致 Lambda [擴展](lambda-concurrency.md)和使用您帳戶的所有可用並行處理。為了減少意外迴圈的影響，Lambda 可在特定類型的遞迴迴圈發生後不久偵測到它們。當 Lambda 偵測到遞迴迴圈時，預設會停止調用函數並通知您。如果您的設計刻意使用遞迴模式，您可以變更函數的預設組態，允許以遞迴方式調用它。如需詳細資訊，請參閱[允許 Lambda 函數在遞迴迴圈中執行](#invocation-recursion-disable)。

**Topics**
+ [

## 了解遞迴迴圈偵測
](#invocation-recursion-concepts)
+ [

## 支援的 AWS 服務 和 SDKs
](#invocation-recursion-supported)
+ [

## 遞迴迴圈通知
](#invocation-recursion-monitoring)
+ [

## 回應遞迴迴圈偵測通知
](#invocation-recursion-responding)
+ [

## 允許 Lambda 函數在遞迴迴圈中執行
](#invocation-recursion-disable)
+ [

## 支援 Lambda 遞迴迴圈偵測功能的區域
](#invocation-recursion-regions)

## 了解遞迴迴圈偵測
<a name="invocation-recursion-concepts"></a>

Lambda 中的遞迴迴圈偵測透過追蹤事件來運作。Lambda 是事件驅動型運算服務，可在特定事件發生時執行函數程式碼。例如，將項目新增至 Amazon SQS 佇列或 Amazon Simple Notiﬁcation Service (Amazon SNS) 主題時。Lambda 會將事件以 JSON 物件的形式傳遞至函數，其中包含系統狀態中的變更資訊。當事件導致函數執行時，這稱為*調用*。

若要偵測遞迴迴圈，Lambda 會使用 [AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html) 追蹤標頭。當[支援遞迴迴圈偵測的AWS 服務](#invocation-recursion-supportedservices) 將事件傳送至 Lambda 時，這些事件會自動使用中繼資料進行註解。當您的 Lambda 函數 AWS 服務 使用支援的 [AWS SDK 版本將其中一個事件寫入到另一個支援的事件時](#invocation-recursion-supportedsdks)，它會更新此中繼資料。更新後的中繼資料包含事件調用函數的次數計數。

**注意**  
您不需要啟用 X-Ray 作用中追蹤，即可使用此功能。依預設，所有 AWS 客戶都會開啟遞迴迴路偵測。使用此功能無需支付任何費用。

*請求鏈*是由相同觸發事件引起的一系列 Lambda 調用。例如，假設 Amazon SQS 佇列調用 Lambda 函數。然後，Lambda 函數會將已處理的事件傳回相同的 Amazon SQS 佇列，然後再次調用函數。在此範例中，函數的每次調用都屬於相同的請求鏈。

如果您的函數在相同的請求鏈中被調用大約 16 次，則 Lambda 會自動停止該請求鏈中的下一個函數調用並通知您。如果函數設有多個觸發條件，來自其他觸發條件的調用不會受影響。

**注意**  
即使來源佇列再驅動政策的 `maxReceiveCount` 設定高於 16，Lambda 遞迴保護也不會阻止 Amazon SQS 在偵測到遞迴迴圈並終止後重試訊息。當 Lambda 偵測到遞迴迴圈並捨棄後續調用時，會將 `RecursiveInvocationException` 傳回至事件來源映射。這會增加訊息上的 `receiveCount` 值。Lambda 會繼續重試訊息，並繼續封鎖函數調用，直至 Amazon SQS 判斷超過 `maxReceiveCount`，並將訊息傳送至設定的無效字母佇列。

如果您為函數設定了[故障時的目的地](invocation-async-retain-records.md#invocation-async-destinations)或[無效字母佇列](invocation-async-retain-records.md#invocation-dlq)，則 Lambda 也會將事件從已停止的調用中傳送至目的地或無效字母佇列。為函式設定目的地或無效字母佇列時，請勿使用函式也在使用的事件觸發程序或事件來源映射。若將事件傳送至調用函式的同一個資源，則可能會建立另一個遞迴迴圈，且此迴圈同樣會被終止。若關閉遞迴迴圈偵測功能，此類迴圈不會被終止。

## 支援的 AWS 服務 和 SDKs
<a name="invocation-recursion-supported"></a>

Lambda 只能偵測包含特定支援的遞迴迴圈 AWS 服務。若要偵測遞迴迴圈，您的函數也必須使用其中一個支援的 AWS SDKs。

### 支援的 AWS 服務
<a name="invocation-recursion-supportedservices"></a>

Lambda 目前可偵測函數、Amazon SQS、Amazon S3 和 Amazon SNS 之間的遞迴迴圈。Lambda 也會偵測僅由 Lambda 函數組成的迴圈，這些函數可以同步或非同步相互調用。下圖顯示 Lambda 可以偵測的一些迴圈範例：

![\[Lambda 函數、Amazon SNS、Amazon S3 和 Amazon SQS 佇列之間的遞迴迴圈圖示。\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/RunawayWorkloadDetected_v3.png)


當 Amazon DynamoDB AWS 服務 等其他 形成迴圈的一部分時，Lambda 目前無法偵測並停止它。

由於 Lambda 目前僅偵測涉及 Amazon SQS、Amazon S3 和 Amazon SNS 的遞迴迴圈，因此涉及其他 的迴圈仍可能導致 Lambda 函數 AWS 服務 意外使用。

為了防止向您的 收取意外費用 AWS 帳戶，建議您設定 [Amazon CloudWatch 警示](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html)，以提醒您不尋常的使用模式。例如，可以設定 CloudWatch，以便在 Lambda 函數並行處理或調用出現峰值時通知您。也可以設定[帳單警示](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html)，當帳戶中的支出超過指定的閾值時通知您。或者，可以使用 [AWS Cost Anomaly Detection](https://docs.aws.amazon.com/cost-management/latest/userguide/manage-ad.html) 來提醒您不尋常的帳單模式。

### 支援的 AWS SDKs
<a name="invocation-recursion-supportedsdks"></a>

若要讓 Lambda 偵測遞迴迴圈，函數必須使用下列其中一個 SDK 版本或更高版本：


| 執行時期 | 最低必要 AWS SDK 版本 | 
| --- | --- | 
|  Node.js  |  2.1147.0 (SDK 版本 2) 3.105.0 (SDK 版本 3)  | 
|  Python  |  1.24.46 (boto3) 1.27.46 (botocore)  | 
|  Java 8 和 Java 11  |  2.17.135  | 
|  Java 17  |  2.20.81  | 
|  Java 21  |  2.21.24  | 
|  .NET  |  3.7.293.0  | 
|  Ruby  |  3.134.0  | 
|  PHP  |  3.232.0  | 
|  Go  |  V2 SDK 1.57.0  | 

Python 和 Node.js 等某些 Lambda 執行時間包含 AWS SDK 的版本。如果函數執行期中包含的 SDK 版本低於所需的最低版本，則可以將支援的 SDK 版本新增到函數的部署套件。您也可以使用 [Lambda 層](chapter-layers.md)將支援的 SDK 版本新增至函數。如需每個 Lambda 執行期包含的 SDK 清單，請參閱 [Lambda 執行期](lambda-runtimes.md)。

## 遞迴迴圈通知
<a name="invocation-recursion-monitoring"></a>

當 Lambda 停止遞迴迴圈時，您會透過 [Health 儀板表](https://aws.amazon.com/premiumsupport/technology/aws-health-dashboard/) 和電子郵件接收通知。也可以使用 CloudWatch 指標來監控 Lambda 已停止的遞迴調用次數。

### Health 儀板表 通知
<a name="invocation-recursion-phd"></a>

當 Lambda 停止遞迴調用時， 會在**您的帳戶運作**狀態頁面的[開啟和最近問題](https://health.aws.amazon.com/health/home#/account/dashboard/open-issues)下 Health 儀板表 顯示通知。請注意，在 Lambda 停止遞迴調用後，可能需要 3.5 小時才會顯示此通知。如需有關在 中檢視帳戶事件的詳細資訊 Health 儀板表，請參閱《[AWS 運作狀態使用者指南》中的運作狀態儀表板 – 您的帳戶運作狀態入門](https://docs.aws.amazon.com/health/latest/ug/getting-started-health-dashboard.html)。 *AWS *

### 電子郵件提醒
<a name="invocation-recursion-email"></a>

當 Lambda 第一次停止函數的遞迴調用時，會傳送電子郵件提醒給您。對於 AWS 帳戶中的每個函數，Lambda 每 24 小時最多傳送一封電子郵件。Lambda 傳送電子郵件通知後，即使 Lambda 停止函數的進一步遞迴調用，在接下來的 24 小時也不會再收到該函數的任何電子郵件。請注意，在 Lambda 停止遞迴調用後，可能需要 3.5 小時才會收到此電子郵件提醒。

Lambda 會傳送遞迴迴圈電子郵件提醒給您 AWS 帳戶的主要帳戶聯絡人和替代操作聯絡人。如需有關檢視或更新帳戶中電子郵件地址的資訊，請參閱《AWS 一般參考》**中的[更新聯絡資訊](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-update-contact.html)。

### Amazon CloudWatch 指標
<a name="invocation-recursion-cloudwatch"></a>

[CloudWatch 指標](monitoring-metrics-types.md)`RecursiveInvocationsDropped`會記錄 Lambda 已停止的函數調用次數，因為您的函數已在單一請求鏈中調用大約 16 次。Lambda 會在停止遞迴調用時立即發出此指標。若要檢視此指標，請按照[在 CloudWatch 主控台上檢視指標](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html#monitoring-metrics-console)的說明進行操作，並選擇指標 `RecursiveInvocationsDropped`。

## 回應遞迴迴圈偵測通知
<a name="invocation-recursion-responding"></a>

當函數被同一觸發事件調用大約 16 次時，Lambda 會停止該事件的下一個函數調用，以中斷遞迴迴圈。若要防止 Lambda 已中斷的遞迴迴圈再次發生，請執行下列動作：
+ 將函數的可用[並行處理](lambda-concurrency.md)降為零，這會限制所有將來的調用。
+ 移除或停用正在調用函數的觸發條件或事件來源映射。
+ 識別並修正程式碼瑕疵，將事件寫回叫用函數 AWS 的資源。當您使用變數來定義函數的事件來源和目標時，就會出現常見的缺陷來源。檢查兩個變數沒有使用相同的值。

此外，如果 Lambda 函數的事件來源是 Amazon SQS 佇列，則請考慮在來源佇列上[設定無效字母佇列](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-dead-letter-queue.html)。

**注意**  
請確定在來源佇列上設定無效字母佇列，而不是在 Lambda 函數上。您在函數上設定的無效字母佇列用於佇列的[非同步調用函數](invocation-async.md)，而不是事件來源佇列。

如果事件來源是 Amazon SNS 主題，則請考慮為函數新增[故障時的目的地](invocation-async-retain-records.md#invocation-async-destinations)。

**將函數的可用並行處理降為零 (主控台)**

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

1. 選擇 函數的名稱。

1. 選擇**調節**。

1. 在**調節函數**對話方塊中，選擇**確認**。

**若要移除函數的觸發條件或事件來源映射 (主控台)**

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

1. 選擇 函數的名稱。

1. 選擇**組態**索引標籤，然後**觸發條件**。

1. 在**觸發條件**下，選取要刪除的觸發條件或事件來源映射，然後選擇**刪除**。

1. 在**刪除觸發條件**對話方塊中，選擇**刪除**。

**若要停用函數的事件來源映射 (AWS CLI)**

1. 若要尋找您要停用之事件來源映射的 UUID，請執行 AWS Command Line Interface (AWS CLI) [list-event-source-mappings](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/list-event-source-mappings.html) 命令。

   ```
   aws lambda list-event-source-mappings
   ```

1. 若要停用事件來源映射，請執行 following AWS CLI [update-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) 命令。

   ```
   aws lambda update-event-source-mapping --function-name MyFunction \
   --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 --no-enabled
   ```

## 允許 Lambda 函數在遞迴迴圈中執行
<a name="invocation-recursion-disable"></a>

如果您的設計刻意使用遞迴迴圈，您可以設定 Lambda 函數，以允許以遞迴方式調用它。我們建議您避免在設計中使用遞迴迴圈。實作錯誤可能會導致使用您所有 AWS 帳戶可用的並行進行遞迴調用，以及向您的 帳戶收取意外費用。

**重要**  
如果您使用遞迴迴圈，請謹慎處理。實作最佳實務防護措施，將實作錯誤的風險降至最低。若要進一步了解使用遞迴模式的最佳實務，請參閱 Serverless Land 中的 [Recursive patterns that cause run-away Lambda functions](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway)。

您可以設定函數，以允許使用 Lambda 主控台、 AWS Command Line Interface (AWS CLI) 和 [PutFunctionRecursionConfig](https://docs.aws.amazon.com//lambda/latest/api/API_PutFunctionRecursionConfig.html) API 進行遞迴迴圈。您也可以在 AWS SAM 和 中設定函數的遞迴迴圈偵測設定 CloudFormation。

依預設，Lambda 會偵測並終止遞迴迴圈。除非設計刻意使用遞迴迴圈，否則建議不要變更函數的預設組態。

請注意，當您設定函數以允許遞迴迴圈時，不會發出 [CloudWatch 指標](monitoring-metrics-types.md#invocation-metrics) `RecursiveInvocationsDropped`。

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

**若要允許函數在遞迴迴圈中執行 (主控台)**

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

1. 選擇函數的名稱以開啟函數詳細資訊頁面。

1. 選擇**組態**標籤，然後選擇**並行和遞迴偵測**。

1. 除了**遞迴迴圈偵測**，選擇**編輯**。

1. 選取**允許遞迴迴圈**。

1. 選擇**儲存**。

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

您可以使用 [PutFunctionRecursionConfig](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionRecursionConfig.html) API 來允許在遞迴迴圈中調用函數。為遞迴迴圈參數指定 `Allow`。例如，您可以使用 `put-function-recursion-config` AWS CLI 命令呼叫此 API：

```
aws lambda put-function-recursion-config --function-name yourFunctionName --recursive-loop Allow
```

------

您可以將函數的組態變更回預設設定，以便 Lambda 在偵測到遞迴迴圈時將其終止。使用 Lambda 主控台或 AWS CLI編輯函數的組態。

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

**若要設定函數以終止遞迴迴圈 (主控台)**

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

1. 選擇函數的名稱以開啟函數詳細資訊頁面。

1. 選擇**組態**標籤，然後選擇**並行和遞迴偵測**。

1. 除了**遞迴迴圈偵測**，選擇**編輯**。

1. 選取**終止遞迴迴圈**。

1. 選擇**儲存**。

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

您可以使用 [PutFunctionRecursionConfig](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionRecursionConfig.html) API 來設定函數，以便 Lambda 在偵測到遞迴迴圈時將其終止。為遞迴迴圈參數指定 `Terminate`。例如，您可以使用 `put-function-recursion-config` AWS CLI 命令呼叫此 API：

```
aws lambda put-function-recursion-config --function-name yourFunctionName --recursive-loop Terminate
```

------

## 支援 Lambda 遞迴迴圈偵測功能的區域
<a name="invocation-recursion-regions"></a>

所有[商業區域](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#region)都支援 Lambda 遞迴迴圈偵測，但墨西哥 (中部) 與亞太區域 (紐西蘭) 除外。