最近は仕事の一つとして、機械学習用のワークフローを作成しています。ワークフローを作成するサービスやソフトウェアはいくつかありますが、それら中でもAWS Step Functionsを使おうと考えています。今回の記事は、AWS Step Functionsについて調べたことを簡単にまとめた内容となっています。
Step Functionsとは?
AWS Step Functionsとは、ワークフローを定義して、実行・管理できるマネージドサービスです。AWS上の各サービスをコンポーネントとしてワークフローを定義することができます。また、定義したワークフローは、以下のようなグラフィカルなコンソールで確認できます。
Step Functionsで何ができるか?
Step Functionsを使うことで、さまざまなタスクで構成される複雑なワークフローを簡単に定義できます。たとえば、画像を複数のフォーマットに変換し、拡大縮小してAmazon Rekognitionで分析するプロセスは、各タスクをLambda関数で記述し、ワークフローとして定義することで、簡単に実行できます。
Step Functionsがなぜ必要か?
Step Functionsを使うことで、各コンポーネントを再利用可能な形で書くことができます。Lambdaだけでワークフローを書こうとすると、一つのLambda関数内にすべての処理を書くか、Lambda関数内から別のLambda関数を呼ぶ必要があります。一つのLambda関数で書くとメンテナンスが難しくなるという欠点があり、Lambda関数内から別の関数を呼び出すと、関数間が密結合になり、再利用しにくい関数になるという欠点があります。
Step Functionsの料金
Step Functionsは状態遷移ごとに課金されます。最初の4000回の状態遷移については一月の無料枠の範囲内なので課金されません。それ以降は状態遷移あたりに課金されます。リージョンによって金額は異なるのですが、バージニア北部の場合、1000回の状態遷移で0.025 USDが課金されます。金額の詳細は以下を参照すると良いでしょう。
Step Functionsの使い方
ワークフローの定義は、Amazon States Languageを使って行います。Amazon States Languageを使うことで、ステートマシンをJSON形式で宣言的に記述することができます。たとえば、以下のように記述します。
{ "Comment": "A Hello World example of the Amazon States Language using a Pass state", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Pass", "Result": "Hello World!", "End": true } } }
JSONで書くと一見複雑に見えるのですが、図にすると以下のようにシンプルです。
このJSONで記述したステートマシンには、状態とその間の関係を記述していきます。状態はStates
の中に書いていきます。上のJSONの場合は状態としてHelloWorld
だけが存在しています。StartAt
にはステートマシンの開始状態を指定します。今回の場合はHelloWorld
ステートから始まるということを示しています。End: true
がある場合は実行を停止します。
Type
は状態のタイプを指定するフィールドです。上の場合はタイプとしてPass
が指定されていますが、これは入力に何もせずに出力するという意味があります。Result
はPass状態からの出力を書くフィールドで、今回の場合は「Hello World!」が出力されます。
もう少し複雑な例について見てみましょう。以下の例では状態が複数含まれています。
{ "Comment": "An example of the Amazon States Language using a choice state.", "StartAt": "FirstState", "States": { "FirstState": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FUNCTION_NAME", "Next": "ChoiceState" }, "ChoiceState": { "Type" : "Choice", "Choices": [ { "Variable": "$.foo", "NumericEquals": 1, "Next": "FirstMatchState" }, { "Variable": "$.foo", "NumericEquals": 2, "Next": "SecondMatchState" } ], "Default": "DefaultState" }, "FirstMatchState": { "Type" : "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:OnFirstMatch", "Next": "NextState" }, "SecondMatchState": { "Type" : "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:OnSecondMatch", "Next": "NextState" }, "DefaultState": { "Type": "Fail", "Error": "DefaultStateError", "Cause": "No Matches!" }, "NextState": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FUNCTION_NAME", "End": true } } }
図にすると以下のようになります。図を見ると条件分岐が入っていることがわかります。
このステートマシンはStartAt
にFirstState
が指定されていることから、FirstState
ステートから開始されることがわかります。そのFirstState
ステートはType
、Resource
、Next
フィールドを持ちます。Type
にTask
が指定されていると、このステートで一つの作業が実行されることを表しています。どんな作業が実行されるのかはResource
に指定します。今回の場合はLambda関数が指定されていることがわかります。Next
には次に遷移する状態を指定します。
次の状態であるChoiceState
はそのタイプがChoice
になっていることが確認できます。タイプをChoice
にすることで、ステートマシンに条件分岐を実装できます。Choices
フィールドの中に条件分岐のルールを書き、どれにもマッチしない場合はDefault
で指定した状態に遷移します。
Choices
フィールドの中身を見てみましょう。
{ "Variable": "$.foo", "NumericEquals": 1, "Next": "FirstMatchState" }
Variable
フィールドには条件分岐の対象となるデータを指定します。今回の場合は$.foo
を指定しているので、ステートマシンの入力からfoo
フィールドの値を取り出して使うことを示しています。
{ "foo": 1 }
その次には比較するタイプを指定します。上の例の場合、NumericEquals
を指定しているので、Variable
の値が比較条件に指定した値と数値的に等しいかを検証します。比較結果が真であればNext
フィールドに指定したステートに遷移します。
残りの部分は、これまでに説明した内容を繰り返し適用しているだけです。
おわりに
今回はAWS Step Functionsの概要について紹介しました。次回の記事ではStep Functionsを使った機械学習/自然言語処理向けのワークフローを構築してみます。