

# 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 のサービス および SDK](#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 関数がこれらのイベントの 1 つを、サポートされている別の 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` 値を増加します。Amazon SQS が `maxReceiveCount` の超過を判定して設定されたデッドレターキューにメッセージを送信するまで、Lambda はメッセージを再試行し続け、関数の呼び出しをブロックし続けます。

[障害発生時の宛先](invocation-async-retain-records.md#invocation-async-destinations)または[デッドレターキュー](invocation-async-retain-records.md#invocation-dlq)が関数に設定されている場合、Lambda はその停止した呼び出しからのイベントを指定された宛先またはデッドレターキューにも送信します。関数に宛先またはデッドレターキューを設定する場合は、関数でも使用されているイベントトリガーまたはイベントソースマッピングを使用しないようにしてください。関数を呼び出すのと同じリソースにイベントを送信すると、別の再帰ループが作成されることがあり、このループも終了します。再帰ループ検出をオプトアウトすると、このループは終了しません。

## サポートされている AWS のサービス および SDK
<a name="invocation-recursion-supported"></a>

Lambda が検出できるのは、サポートされている特定の AWS のサービス を含む再帰ループのみです。再帰ループを検出するには、関数はサポートされている AWS SDK のいずれかを使用する必要もあります。

### サポートされる 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/ja_jp/lambda/latest/dg/images/RunawayWorkloadDetected_v3.png)


Amazon DynamoDB などの別の AWS のサービス がループの一部を形成してる場合、現時点では Lambda はそのループを検出して停止することはできません。

現時点では、Lambda は Amazon SQS、Amazon S3、および Amazon SNS に関連する再帰ループのみを検出するため、他の AWS のサービス が関与するループによって Lambda 関数が意図しない形で使用される可能性があります。

ユーザーの AWS アカウント に予期しない料金が請求されるのを防ぐため、[Amazon CloudWatch アラーム](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html)を設定して、通常とは異なる使用パターンが警告されるようにすることをお勧めします。例えば、Lambda 関数の同時実行数や呼び出し回数の急増が検知された場合に、CloudWatch を設定しておくとユーザーに通知が送信されます。また、[請求アラーム](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 SDK
<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 Dashboard](https://aws.amazon.com/premiumsupport/technology/aws-health-dashboard/) やメールで通知が届きます。CloudWatch メトリクスを使用して、Lambda が停止した再帰呼び出しの数をモニタリングすることもできます。

### Health Dashboard の通知
<a name="invocation-recursion-phd"></a>

Lambda が再帰呼び出しを停止すると、Health Dashboard は、**[アカウントヘルス] **ページの [[未解決の問題と最近の問題]](https://health.aws.amazon.com/health/home#/account/dashboard/open-issues) に通知を表示します。Lambda が再帰呼び出しを停止してからこの通知が表示されるまでに、最大 3.5 時間かかる場合があることに注意してください。Health Dashboard でのアカウントイベントの表示に関する詳細については、「*AWS Health ユーザーガイド*」の「[Getting started with your AWS Health Dashboard – Your account health](https://docs.aws.amazon.com/health/latest/ug/getting-started-health-dashboard.html)」を参照してください。

### E メールアラート
<a name="invocation-recursion-email"></a>

Lambda が関数の再帰呼び出しを初めて停止すると、E メールアラートが送信されます。Lambda は、AWS アカウント の各関数につき 24 時間ごとに最大 1 通のメールを送信します。Lambda から E メール通知が送信された後の 24 時間は、Lambda によって関数の再帰呼び出しが再度停止された場合でも、その関数に関するメールが届きません。Lambda が再帰呼び出しを停止してからこの E メールアラートを受信するまでに、最大 3.5 時間かかる場合があることに注意してください。

再帰的なループに関する E メールアラートは、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` には、1 回のリクエストチェーンで関数が約 16 回を超えて呼び出されたために Lambda が停止した関数の呼び出し回数が記録されます。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)を 0 に減らすと、以降の呼び出しがすべてスロットリングされます。
+ 関数を呼び出すトリガーやイベントソースマッピングを削除または無効にします。
+ 関数を呼び出している 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. **[Configuration]** タブを選択し、**[Triggers]** を選択します。

1. **[Triggers]** で、削除するトリガーまたはイベントソースマッピングを選択し、**[Delete]** を選択します。

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. イベントソースマッピングを無効にするには、次の 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 の「[Lambda 関数が暴走する原因となる再帰パターン](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>

Lambda 再帰ループ検出は、メキシコ (中部) とアジアパシフィック (ニュージーランド) を除くすべての[商用リージョン](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#region)でサポートされています。