S3のイベント通知などで動作させるバッチ系のAWS Lambdaを設計する際の注意点とAWS Lambdaがタイムアウトになった場合の検知方法についてです。
非同期AWS Lambda設計時の注意点
非同期Lambdaの場合、エラー発生時のリトライ回数がデフォルトで2回になっています。
バッチ系の処理をしている場合、処理が2回行われると困る場面もあると思いますので、そのような場合はリトライ回数を0回に設定しておきましょう。
明示的に正常、エラーを返却しているような関数でも予期せぬAWS障害等でLambdaがタイムアウトになる可能性もあるので要注意です。
非同期AWS Lambdaのタイムアウト検知
非同期Lambdaでタイムアウトが発生した場合、
SQS、SNS、Lambda、EventBridge
に通知をすることが可能です。
別のアプローチとしてデッドレターキューを利用する方法もありますが
今回はLambdaに通知するサンプルを記載します。
AWS SAMテンプレートサンプル
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
error-notice-sample
Resources:
# タイムアウトエラーを発生させるLambda
LogOutputFunc:
Type: AWS::Serverless::Function
Properties:
CodeUri: log_output_func/
Handler: app.lambda_handler
Runtime: python3.8
Events:
LogOutputFuncEvent:
Type: S3
Properties:
Bucket:
Ref: MyBucket
Events: s3:ObjectCreated:*
EventInvokeConfig:
# 非同期Lambdaのリトライ回数を0回に設定
MaximumRetryAttempts: 0
DestinationConfig:
# エラー発生時に呼び出すLambdaを指定
OnFailure:
Type: Lambda
Destination: !GetAtt ErrorNoticeFunc.Arn
# LogOutputFuncでエラー発生した場合に起動するLambda
ErrorNoticeFunc:
Type: AWS::Serverless::Function
Properties:
CodeUri: error_notice_func/
Handler: app.lambda_handler
Runtime: python3.8
MyBucket:
Type: "AWS::S3::Bucket"
Properties:
BucketName: "2021-yy-dd-mytestbucket"
AccessControl: Private
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
エラー通知側AWS LambdaのEventオブジェクト
ErrorNoticeFuncが呼び出された時にどのようなEventデータが取得できるか?
ですが、以下は実行時例外発生時のEventデータサンプルです。
スタックトレースやリクエストパラメータ等も格納されています。
{
'version': '1.0',
'timestamp': '2021-12-08T12:11:29.345Z',
'requestContext':
{'requestId': 'xxxx-xxxx-xxxx',
'functionArn': 'arn:aws:lambda:ap-northeast-1:xxx:function:xxxfuncname:$LATEST',
'condition': 'RetriesExhausted',
'approximateInvokeCount': 1},
'requestPayload':
{'Records': [
{'eventVersion': '2.1',
'eventSource': 'aws:s3',
'awsRegion': 'ap-northeast-1',
'eventTime': '2021-12-08T12:11:27.454Z',
'eventName': 'ObjectCreated:Put',
'userIdentity': {'principalId': 'AWS:xxxx'},
'requestParameters': {
'sourceIPAddress': 'xxx.xx.38.00'},
'responseElements': {
'x-amz-request-id': 'xxx',
'x-amz-id-2': 'xxx'},
` 's3': {'s3SchemaVersion': '1.0',
'configurationId': 'xxx',
'bucket': {'name': 'xxx',
'ownerIdentity':
{'principalId': 'xxx'},
'arn': 'arn:aws:s3:::bucketname'},
'object': {'key': '6.html', 'size': 1584,
'eTag': 'xxx',
'sequencer': 'xxxx'}}}]},
'responseContext':
{'statusCode': 200,
'executedVersion': '$LATEST',
'functionError': 'Unhandled'},
'responsePayload': {
'errorMessage': "'ab'",
'errorType': 'KeyError',
'stackTrace': [' File "/var/task/app.py",
line 12, in lambda_handler\n a = map["ab"]\n']}}
タイムアウト発生時も同様のEventが渡されます。
エラーメッセージは以下のように「Task timed out after xxx」が出力されます。
{'errorMessage':
'2021-12-08T12:26:13.100Z xxxx-xxxx Task timed out after 3.00 seconds'}}
以上