少し前にSQSとの無限ループ検出、停止が実装されましたが、ついにもっともメジャーなLambda↔S3間の検知も来ましたね。
裏ではX-Rayが使われてるんでしたっけ?
概要
AWS Lambda は、再帰ループ検出機能をデフォルトで有効化、Lambda と Amazon S3 間での意図しない再帰ループを自動的に検出・停止。
これにより、設定ミスやコードの欠陥による無駄な課金や暴走を防る。
課金抑制: 意図しない再帰ループの発生を防止。
通知機能: 問題発生時に AWS Health Dashboard でトラブルシューティング情報を提供。
意図的な再帰: 必要に応じて PutFunctionRecursionConfig API で検出を無効化可能。
この機能は全リージョンで利用可能です。詳細は Lambda ドキュメント を参照。
検証
テスト用コード
import boto3
import random
import string
import os
s3_client = boto3.client('s3')
def generate_random_filename(length=10, extension=".txt"):
"""ランダムなファイル名を生成"""
random_str = ''.join(random.choices(string.ascii_letters + string.digits, k=length))
return random_str + extension
def lambda_handler(event, context):
"""Lambda 関数のエントリポイント"""
# S3 バケット名(環境変数から取得)
bucket_name = os.environ.get('S3_BUCKET_NAME')
if not bucket_name:
return {
"statusCode": 400,
"body": "環境変数 'S3_BUCKET_NAME' を設定してください。"
}
# ランダムなファイル名を生成
random_filename = generate_random_filename()
# アップロードするデータ(ここでは例として固定のテキストを使用)
file_content = "lambda-s3-loop-detect-test"
try:
# S3 にアップロード
s3_client.put_object(Bucket=bucket_name, Key=random_filename, Body=file_content)
return {
"statusCode": 200,
"body": f"ファイル '{random_filename}' を S3 バケット '{bucket_name}' にアップロードしました。"
}
except Exception as e:
return {
"statusCode": 500,
"body": f"アップロード中にエラーが発生しました: {e}"
}
テスト実行
ループを設定
ループ順序
- Lambda によってファイルが作成
- S3のイベント通知でLambdaが起動
- 起動されたLambdaによってS3へファイルが作成
- S3のイベント通知でLambdaが起動
をずっとくりかえる感じです、公式的には16回の実行で止まるはず。
発火します
CloudWatch 上にメトリクスも出力されます
Recursive invocations dropped メトリクス
アラームなどを設定しておくとよいかもしれません
対応外のケースもあるようなので、慢心しないように注意しましょう