のべラボ.blog

Tech Blog | AWS や サーバーレスやコンテナ などなど

AWS Step Functions の Map ステートを触ってみる

AWS Step Functions Map ステートで色々試したいことがあるのですが、その事前準備として今回は Map ステートの基本的な機能を確認してみます。

Map は、配列の要素数に応じて同じ処理を並列に実行してくれるステートです。

docs.aws.amazon.com

例えば Map ステート内で Lambda 関数 Aを呼び出すステートを設定し、その Map ステートに対して 要素数 3 の配列を指定すると、Lambda 関数 Aが3並列で呼び出されます。

今回は、シンプルにこの動作を確認してみます。

まず、Map ステートから呼び出す Lambda 関数を作成します。今回は Python 3.9 で作成しました。

このLambda 関数の並列実行を後で確認しやすくするため、このLambda 関数は敢えて 実行に 3 秒かかるように実装しています。

import json
import time

def lambda_handler(event, context):
    # TODO implement
    time.sleep(3)
    print(event)
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

よって、Lambda 関数のタイムアウトを 5 秒に設定しておきましょう。

AWS マネジメントコンソールからだと、[設定]タブを選択して、左側メニューで [一般設定]を選択して、[一般設定]セクションから設定できます。

https://cdn-ak.f.st-hatena.com/images/fotolife/n/neob/20221106/20221106154307.png

次は、この Lambda 関数を呼び出す AWS Step Functions のステートマシンです。

下記は例ですが、FunctionName は、作成しておいた Lambda 関数の ARN を指定します。

{
  "Comment": "test map state",
  "StartAt": "Map",
  "States": {
    "Map": {
      "Type": "Map",
      "End": true,
      "Iterator": {
        "StartAt": "Lambda Invoke",
        "States": {
          "Lambda Invoke": {
            "Type": "Task",
            "Resource": "arn:aws:states:::lambda:invoke",
            "OutputPath": "$.Payload",
            "Parameters": {
              "Payload.$": "$",
              "FunctionName": "arn:aws:lambda:ap-northeast-1:123412341234:function:maptest"
            },
            "Retry": [
              {
                "ErrorEquals": [
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException"
                ],
                "IntervalSeconds": 2,
                "MaxAttempts": 6,
                "BackoffRate": 2
              }
            ],
            "End": true
          }
        }
      },
      "MaxConcurrency": 40
    }
  }
}

このJSON を使用してステートマシンを作成します。

AWS マネジメントコンソールから作成する場合は、AWS Step Functions のページで [ステートマシンの作成] を選択して、[コードでワークフローを記述] を選択し、[定義] セクションに JSON を貼り付けます。

https://cdn-ak.f.st-hatena.com/images/fotolife/n/neob/20221106/20221106154640.png

その後、[次へ] ボタンを選択して、ステートマシンに任意の名前をつけて [ステートマシンの作成] をクリックします。

作成したステートマシンは下図のようになります。

https://cdn-ak.f.st-hatena.com/images/fotolife/n/neob/20221106/20221106155022.png

また、Workflow Studio でみると、下図のようになります。

https://cdn-ak.f.st-hatena.com/images/fotolife/n/neob/20221106/20221106155052.png

では、作成したステートマシンを実行してみます。

今回は、ステートマシンのパラメータを配列にして、そのまま Map ステートに渡す前提にしていますので、パラメータに JSONの配列を指定します。

内容は、どんなものでもかまいませんが、要素を識別できるような値にすると、あとあと Lambda 関数の実行確認に役立ちます。

下記は例です。

[
  {"id": 1},
  {"id": 2},
  {"id": 3}  
]

では、AWS マネジメントコンソールから実行してみます。作成したステートマシンのページで [実行の開始] ボタンを選択して [入力] に上記のパラメータを指定します。[実行の開始] をクリックします。

https://cdn-ak.f.st-hatena.com/images/fotolife/n/neob/20221106/20221106155217.png

最終的に下図のように、Map ステートと、その内側の Lambda 関数を呼び出すステートが緑色に表示されることを確認します。

https://cdn-ak.f.st-hatena.com/images/fotolife/n/neob/20221106/20221106155335.png

ページを少し下にスクロールすると、[イベント] セクションが表示されています。その中から Lambda Invoke ステップの [Logs] のリンクを選択すると、CloudWatch Logs のページが表示されます。

https://cdn-ak.f.st-hatena.com/images/fotolife/n/neob/20221106/20221106155630.png

ここで、3 つのログストリームが作成されていることを確認します。これは 3つの Lambda関数の実行環境が作成されて、それぞれログが出力されたことを表します。

https://cdn-ak.f.st-hatena.com/images/fotolife/n/neob/20221106/20221106155813.png

それぞれログをみてみましょう。ステートマシンのパラメータで指定した配列の要素が出力されています。下記は例です。

START RequestId: d348870f-69a7-4778-953b-e8dccd23b444 Version: $LATEST
{'id': 2}
END RequestId: d348870f-69a7-4778-953b-e8dccd23b444
REPORT RequestId: d348870f-69a7-4778-953b-e8dccd23b444  Duration: 3005.46 ms    Billed Duration: 3006 ms    Memory Size: 128 MB Max Memory Used: 36 MB  Init Duration: 101.36 ms    

これで、Map ステートから 3並列で Lambda関数を呼び出せたことを確認できました。

Map ステートでやりたいことは他にもあるのですが、まずは超基本の動作確認を行いました。

また Map ステートのネタで記事を書きたいと思います!

/* -----codeの行番号----- */