Lambda関数でDeadLetterQueue(DLQ)を試す

AWSのLambda関数をイベントで起動した時、複数回エラーを起こしたら、DeadLetterQueue、すなわちDLQを飛ばしたい。DLQを試すもの。Cloudformation使う。DLQはSNSとSQSが指定できるが、今回はSNSを使う。

以下の系を試す。

CloudWatch -> Lambda -(error)-> SNS -> Email

やってみる

CloudWatchで1分ごとにLambda関数を起動するようなものを、Cloudformationwと使って用意する。SNS Topicについては、コンソールから作成する。

SNS Topicを作る

コンソールからSNS Topicを作成する。名前は仮に DeadLetterQueueTopicとする。とりあえずEメールに飛ばすようにしておくと、確認しやすいと思う。

ディレクトリ構成

ディレクトリ構成は以下。__init__.pyは空。

.
├── __init__.py
├── hello_world_function
│   ├── __init__.py
│   ├── hello_world
│   │   ├── __init__.py
│   │   └── app.py
│   └── requirements.txt
├── samconfig.toml
└── template.yaml

という構成でやってみる。

template.yaml

TargetArn に SNS Topic のARNを入れる。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world_function
      Handler: hello_world/app.lambda_handler
      Runtime: python3.8
      Policies:
        - AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/AmazonSNSFullAccess
      Events:
        HelloWorld:
          Type: Schedule
          Properties:
            Schedule: rate(1 minute)
      DeadLetterQueue:
        Type: SNS
        TargetArn: arn:aws:sns:xxxxxxxxxxxxxxxxxx:DeadLetterQueueTopic

samconfig.toml

sam build –use-container の後に sam deploy –guided で作るとよい。以下のようになる。

version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "sam-app"
s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1miie23rwqpqg"
s3_prefix = "sam-app"
region = "ap-northeast-1"
capabilities = "CAPABILITY_IAM"

requirement.txt

空でもいいけど。

requests
six
regex

hello_world/app.py

def lambda_handler(event, context):
    # print(event)
    # raise Exception
    return True

DLQ

sam build --use-container
# 初回で samconfig.tomlがない状態では sam deploy --guided
sam deploy

デプロイすると、1分間にLambda関数が起動する。で、このままだと正常に終了してDLQが飛ばないので、わざとエラーを起こす。そのためには、上記コードの raise Exception のエラーを外してデプロイする。しばらく待っていたら、DLQがSNSに飛ぶ。SNSのSubscriberにEmailを用意しておけば、すぐに確認できる。

後片付け

SNSのトピックは手動で作成したので、手動で消す。

忘れずにスタックを消す。消し忘れると延々とLambda関数が起動し続けることになってしまうので注意。
aws cloudformation delete-stack --stack-name sam-app

DLQ -> SNS -> Lambdaにした時のproperty

Slackとかに飛ばしたい時は、DLQのSNS経由でLambda関数に飛ばすことになる。Lambda関数のeventのpropertyをメモしておく。

{
  "Records": [
    {
      "EventSource": "aws:sns",
      "EventVersion": "1.0",
      "EventSubscriptionArn": "xxxxx",
      "Sns": {
        "Type": "Notification",
        "MessageId": "xxxx",
        "TopicArn": "xxxx"
        "Subject": None,
        "Message": "xxxxxxx",
        "Timestamp": "2021-05-13T03:02:52.129Z",
        "SignatureVersion": "1",
        "Signature": "xxxx",
        "SigningCertUrl": "xxxx",
        "UnsubscribeUrl": "xxxx",
        "MessageAttributes": {
          "RequestID": {
            "Type": "String",
            "Value": "xxxx",
          },
          "ErrorCode": {
            "Type": "String",
            "Value": "200"
          }
        }
      }
    }
  ]
}

気になるのは event.Sns.Message だが、これはシリアライズされたJSON。json.loads()でデシリアライズすると以下のようになる。

{
	"version": "0",
	"id": "xxxx",
	"detail-type": "Scheduled Event",
	"source": "aws.events",
	"account": "xxxx",
	"time": "2021-05-13T02:47:42Z",
	"region": "xxxx",
	"resources": [
		"xxxx",
	],
	"detail": {}
}

resourcesとidから、エラーを起こした元のLambda関数を辿ることができる。

参考URL

ありがとうございました。

関連記事

スポンサーリンク

カテゴリーaws

コメントを残す

メールアドレスが公開されることはありません。