AWS Step Functions入門してみた

こんにちは、クラウドソリューション事業部の本田です。 先日AWS Step Functionsの勉強会があったので参加していました。復習がてらアウトプットということでブログにしてみたいと思います。

AWS Step Functionsについて

AWSの公式ページより引用となりますが、

AWS Step FunctionsとはStep Functions は、AWS Lambda 関数およびその他のビジネスクリティカルなアプリケーションを構築するための AWS のサービスを組み合わせることができるサーバーレスオーケストレーションサービスです。Step Functions のグラフィカルコンソールでは、アプリケーションのワークフローを一連のイベント駆動型ステップとして確認できます。

https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/welcome.html

とありまして、AWS LambdaなどのAWSサービスを組み合わせることができるサービスで、またコンソールから実行したワークフローを グラフなどを通して実行状況などを確認と管理することができるサービスです。

ステートマシンとタスク

ステートマシンとタスクに基づいていまして、ステートマシンは1連のワークフローを指し、タスクはワークフロー内で 実行されるサービスの1つの作業単位を指します。作成方法は、Step Functions Workflow Studioと呼ばれるドラックアンドドロップで作成する方法、Amazon State LanguageかYAMLを使用してコードで作成する方法があります。

今回はStep FunctionsからLambdaを数パターン呼び出してみて、どういったことができるかということをやってみたいと思います。

Step Functionsを動かしてみる

1つのLambdaを呼び出す

まずはStep functionsからLambda関数を呼び出したいと思います。以下のような関数を用意します。Lambdaの設定はデフォルトで問題ありません。

exports.handler = (event, context, callback) => {
    callback(null,"Hello from " + event.who + "!");
};

関数名はStep Functionsから設定するときに使いますので、メモしておきましょう。では早速Step Functionsを作っていきます。

今回はStep Functions Workflow Studioを使い、ドラックアンドドロップで作成します。

左のアクションからLambda invokeを右の図の中にドラックアンドドロップしています。その後、Lambda invokeをクリックし、Function nameで作成したLambda関数を選択しています。

今回のステートマシン名は「Hello」にしておきます。他の設定はデフォルトのままでいきます。作成できたら、早速動かしてみます。

入力を上記に書き換えて、「実行の開始」をクリックすると実行されます。

実行の結果は上記の感じになりました。入力した値が出力されています。これだけならLambdaのコンソールからでもできますが、入力した値と出力した値などの結果はLambdaのコンソールより見やすいかと思います。デバッグなんかで使うのも良いかもしれません。

1つのLambdaを動かしてみましたが、次は出力結果によってその後の処理を変えてみましょう。

Choiceを使ってみる

前段のタスクのアウトプットの内容によって、分岐先を決定できるChoichステートという機能がありますので、次はこちらを使ってみます。そのために以下のLambda関数を用意します。

exports.handler = async (event, context, callback) => {
    const data = ["John","Mike"];
    const response  = {
    "who":data[Math.floor(Math.random() * data.length)]
    };
    console.log(response);
    callback(null,response);
};

JohnかMikeをランダムで返す関数で、出力結果によって分岐するようなステートマシンを作成します。今回はAmazon State Languageを使って作成します。

{
  "Comment": "A description of my state machine",
  "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:xxxxxxxxxxxxxx:function:randomchoice:$LATEST"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 6,
          "BackoffRate": 2
        }
      ],
      "Next": "Choice"
    },
    "Choice": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.who",
          "StringMatches": "John",
          "Next": "Lambda Invoke2"
        }
      ],
      "Default": "Pass"
    },
    "Lambda Invoke2": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "OutputPath": "$.Payload",
      "Parameters": {
        "Payload.$": "$",
        "FunctionName": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxxxx:function:hellofunction:$LATEST"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 6,
          "BackoffRate": 2
        }
      ],
      "End": true
    },
    "Pass": {
      "Type": "Pass",
      "End": true
    }
  }
}

FunctionNameにはLambdaのARNが入ります。Lambda Invokeの出力結果が、who:Johnである場合は、Lambda Invoke2で指定したLambda関数を実行させます。JohnでなければPassし、Lambda Invokeの出力結果をそのまま出力します。可視化すると以下感じになります。

作成できたので早速実行してみます。今回の入力はデフォルトの値のままで大丈夫です。

出力結果がwho:Johnだったパターンです。ChoiceでLambda invoke2が分岐先になっています。

お次は出力結果がwho:Mikeでしたので、ChoiceでPassが分岐先になっています。このようにChoiceを使うことで、出力結果によって分岐させることができました。

最後に

今まで聞いたことはありましたが使ったことのなかったStep Functionsでした。もっと前に触っておけば色々とできなと思ったりしました。今回に限らずですが、資料を読むだけでなくやはり触ってみて理解するというのが大切ですね。実際の業務で落とし込めるようにしていきたいと思います。