Lambda 再帰ループ検出を使用した無限ループの防止
関数を呼び出すのと同じサービスまたはリソースに出力するように Lambda 関数を設定すると、無限再帰ループが作成される可能性があります。例えば、Lambda 関数が Amazon Simple Queue Service (Amazon SQS) キューにメッセージを書き込み、その書き込まれたキューによって同じ関数が呼び出される場合があります。この呼び出しにより、関数はキューに別のメッセージを書き込み、キューによって関数が再び呼び出されます。
意図しない再帰ループが発生すると、AWS アカウント に予期しない料金が請求される可能性があります。ループが原因で Lambda がスケールし、アカウントで利用可能なすべての同時実行性が使用されることもあります。意図しないループの影響を減らすために、Lambda は特定のタイプの再帰ループを発生後すぐに検出します。デフォルトでは、Lambda が再帰ループを検出すると、関数の呼び出しを停止し、ユーザーに通知します。再帰パターンを意図的に使用する仕様になっている場合は、再帰的に呼び出せるように関数のデフォルト設定を変更できます。詳細については「Lambda 関数が再帰ループで動作するようにする」を参照してください。
セクション
再帰ループ検出を理解する
Lambda の再帰ループ検出は、イベントを追跡することで動作します。Lambda はイベント駆動型のコンピューティングサービスで、特定のイベントが発生すると関数コードを実行します。例えば、アイテムが Amazon SQS キューまたは Amazon Simple Notification Service (Amazon SNS) トピックに追加された場合などが挙げられます。Lambda は、システム状態の変化に関する情報を含んだイベントを JSON オブジェクトとして関数に渡します。イベントによって関数が実行されるとき、これを呼び出しと呼びます。
再帰ループを検出するために、Lambda は AWS X-Ray トレースヘッダーを使用します。再帰ループ検出をサポートしている AWS のサービス が Lambda にイベントを送信すると、それらのイベントには自動的にメタデータの注釈が付けられます。Lambda 関数がこれらのイベントの 1 つを、サポートされている別の AWS のサービス に対してサポートされているバージョンの AWS SDK を使用して書き込むと、このメタデータが更新されます。更新されたメタデータには、イベントによって関数が呼び出された回数が含まれます。
注記
この機能を動作させるのに、X-Ray アクティブトレーシングを有効にする必要はありません。再帰ループ検出は、AWS をお使いのすべてのお客様に対してデフォルトでオンになっています。この機能は無料で使用できます。
リクエストチェーンとは、同じトリガーイベントによって発生する Lambda 呼び出しのシーケンスです。例えば、ある Amazon SQS キューが Lambda 関数を呼び出すとします。呼び出された Lambda 関数は、次に、処理されたイベントを同じ Amazon SQS キューに送り返し、そこで関数が再度呼び出されます。この例では、それぞれの関数呼び出しは同じリクエストチェーンに分類されます。
同じリクエストチェーンで関数が 16 回ほど呼び出された場合、Lambda はそのリクエストチェーン内の次の関数呼び出しを自動的に停止し、ユーザーに通知します。関数が複数のトリガーで構成されている場合、他のトリガーからの呼び出しには影響しません。
注記
ソースキューの再処理ポリシーの maxReceiveCount 設定が 16 より大きい場合でも、Lambda 再帰保護は、再帰ループが検出され終了された後に Amazon SQS がメッセージを再試行することを防止しません。Lambda は、再帰ループを検出し、それ以降の呼び出しを中止すると、イベントソースマッピングに RecursiveInvocationException を返します。メッセージの receiveCount 値を増加します。Amazon SQS が maxReceiveCount の超過を判定して設定されたデッドレターキューにメッセージを送信するまで、Lambda はメッセージを再試行し続け、関数の呼び出しをブロックし続けます。
障害発生時の宛先またはデッドレターキューが関数に設定されている場合、Lambda はその停止した呼び出しからのイベントを指定された宛先またはデッドレターキューにも送信します。関数に宛先またはデッドレターキューを設定する場合は、関数でも使用されているイベントトリガーまたはイベントソースマッピングを使用しないようにしてください。関数を呼び出すのと同じリソースにイベントを送信すると、別の再帰ループが作成されることがあり、このループも終了します。再帰ループ検出をオプトアウトすると、このループは終了しません。
サポートされている AWS のサービス および SDK
Lambda が検出できるのは、サポートされている特定の AWS のサービス を含む再帰ループのみです。再帰ループを検出するには、関数はサポートされている AWS SDK のいずれかを使用する必要もあります。
サポートしている AWS のサービス
Lambda は現在、関数、Amazon SQS、Amazon S3、Amazon SNS の間の再帰ループを検出します。Lambda は、Lambda 関数のみで構成されるループも検出します。これらの関数は、同期的に、または非同期的にお互いを呼び出す可能性があります。次の図に、Lambda が検出できるループの例を示します。
Amazon DynamoDB などの別の AWS のサービス がループの一部を形成してる場合、現時点では Lambda はそのループを検出して停止することはできません。
現時点では、Lambda は Amazon SQS、Amazon S3、および Amazon SNS に関連する再帰ループのみを検出するため、他の AWS のサービス が関与するループによって Lambda 関数が意図しない形で使用される可能性があります。
ユーザーの AWS アカウント に予期しない料金が請求されるのを防ぐため、Amazon CloudWatch アラームを設定して、通常とは異なる使用パターンが警告されるようにすることをお勧めします。例えば、Lambda 関数の同時実行数や呼び出し回数の急増が検知された場合に、CloudWatch を設定しておくとユーザーに通知が送信されます。また、請求アラームを設定しておくことで、アカウントでの支出が指定したしきい値を超えたときにも通知を受け取ることができます。AWS Cost Anomaly Detection を使用すると、通常とは異なる請求パターンがあった場合に警告を受け取ることができます。
サポートされている AWS SDK
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 レイヤーを使用して、サポートされている SDK バージョンを関数に追加することもできます。各 Lambda ランタイムに含まれている SDK のリストについては、Lambda ランタイム を参照してください。
再帰ループ通知
Lambda が再帰ループを停止すると、Health Dashboard
Health Dashboard の通知
Lambda が再帰呼び出しを停止すると、Health Dashboard は、[アカウントヘルス] ページの [未解決の問題と最近の問題]
E メールアラート
Lambda が関数の再帰呼び出しを初めて停止すると、E メールアラートが送信されます。Lambda は、AWS アカウント の各関数につき 24 時間ごとに最大 1 通のメールを送信します。Lambda から E メール通知が送信された後の 24 時間は、Lambda によって関数の再帰呼び出しが再度停止された場合でも、その関数に関するメールが届きません。Lambda が再帰呼び出しを停止してからこの E メールアラートを受信するまでに、最大 3.5 時間かかる場合があることに注意してください。
再帰的なループに関する E メールアラートは、Lambda からお客様の AWS アカウント のプライマリアカウント連絡先と代替オペレーション連絡先に送信されます。アカウントのメールアドレスの表示または更新については、AWS 全般のリファレンスの「連絡先情報の更新」を参照してください。
Amazon CloudWatch メトリクス
CloudWatch メトリクスの RecursiveInvocationsDropped には、1 回のリクエストチェーンで関数が約 16 回を超えて呼び出されたために Lambda が停止した関数の呼び出し回数が記録されます。Lambda は再帰呼び出しを停止するとすぐにこのメトリクスを出力します。このメトリクスを表示するには、「CloudWatch コンソールでメトリクスを表示する」に記載の指示に従い、メトリクス RecursiveInvocationsDropped を選択します。
再帰ループ検出通知への対応
同じトリガーイベントによって関数が約 16 回を超えて呼び出された場合、Lambda はそのイベントの次の関数呼び出しを停止して再帰ループを中断します。Lambda が中断した再帰ループの再発を防ぐには、以下を実行してください。
-
関数が同時に実行できる回数を 0 に減らすと、以降の呼び出しがすべてスロットリングされます。
-
関数を呼び出すトリガーやイベントソースマッピングを削除または無効にします。
-
関数を呼び出している AWS リソースにイベントを書き戻すコードを特定し、欠陥を修正します。よくある不具合の原因として、変数を使用して関数のイベントソースとターゲットを定義している場合が挙げられます。両方の変数に同じ値が使用されていないことを確認してください。
さらに、Lambda 関数のイベントソースが Amazon SQS キューの場合は、ソースキューにデッドレターキューを設定することを検討してください。
注記
Lambda 関数ではなく、ソースキューのデッドレターキューを設定するようにしてください。関数で設定したデッドレターキューは、イベントソースキューではなく、関数の非同期呼び出しキューに使用されます。
イベントソースが Amazon SNS トピックの場合は、関数に障害発生時の宛先を追加することを検討してください。
関数で利用できる同時実行数をゼロにするには (コンソール)
Lambda コンソールの [関数]
ページを開きます。 -
関数の名前を選択します。
-
[スロットル] を選択します。
-
[関数のスロットル] ダイアログボックスで、[確認] を選択します。
関数のトリガーまたはイベントソースマッピングを削除するには (コンソール)
Lambda コンソールの [関数]
ページを開きます。 -
関数の名前を選択します。
-
[Configuration] タブを選択し、[Triggers] を選択します。
-
[Triggers] で、削除するトリガーまたはイベントソースマッピングを選択し、[Delete] を選択します。
-
[トリガーの削除] ダイアログボックスで、[削除] を選択します。
関数のイベントソースマッピングを無効にするには (AWS CLI)
-
無効にするイベントソースマッピングの UUID を見つけるには、AWS Command Line Interface (AWS CLI) の list-event-source-mappings
コマンドを実行します。 aws lambda list-event-source-mappings -
イベントソースマッピングを無効にするには、次の AWS CLI update-event-source-mapping
コマンドを実行します。 aws lambda update-event-source-mapping --function-nameMyFunction\ --uuida1b2c3d4-5678-90ab-cdef-EXAMPLE11111--no-enabled
Lambda 関数が再帰ループで動作するようにする
再帰ループを意図的に使用する仕様になっている場合は、再帰的に呼び出せるように Lambda 関数を設定できます。再帰ループを使用する仕様にはしないことをお勧めします。実装エラーが発生すると、自分の AWS アカウントで利用可能なすべての同時実行を使用して再帰呼び出しが行われ、想定外の料金がアカウントに請求される可能性があります。
重要
再帰ループを使用する場合は、その扱いに十分に注意してください。実装エラーのリスクを最小限に抑えるベストプラクティスガードレールを実装します。再帰パターンを使用する際のベストプラクティスの詳細については、Serverless Land の「Lambda 関数が暴走する原因となる再帰パターン
Lambda コンソール、AWS Command Line Interface (AWS CLI)、および PutFunctionRecursionConfig API を使用して再帰ループを許可できるように関数を設定できます。また、AWS SAM と CloudFormation で関数の再帰ループを検出するように設定することもできます。
デフォルトでは、Lambda は再帰ループを検出すると強制的に終了します。再帰ループを意図的に使用する仕様になっている場合を除き、関数のデフォルト設定を変更しないことをお勧めします。
再帰ループを許可するように関数を設定すると、CloudWatch メトリクス RecursiveInvocationsDropped が出力されないことに注意してください。
Lambda が再帰ループを検出したら強制終了するように、関数の設定をデフォルト設定に戻すことができます。関数の設定を編集するには、Lambda コンソールまたは AWS CLI を使用します。
Lambda 再帰ループ検出に対応しているリージョン
Lambda 再帰ループ検出は、メキシコ (中部) とアジアパシフィック (ニュージーランド) を除くすべての商用リージョンでサポートされています。