AWS Step Functions を触ってみた

先日、Serverlessconf Tokyo 2017に参加して、いろいろなサーバーレスアーキテクチャの話を聞き、 AWS Step Functions を使って複数の AWS Lambda を管理しているという話がいろいろと便利そうだったので、触ってみた。

Step Functions を使うと、Lambda のアプリケーションを一連のステップとして視覚的に定義し、複数の Lambda をワークフローとして管理することができるとのこと。

さっそくやってみた。

ステップ 1: ステートマシンに名前を付ける

ダッシュボードの ステートマシンの作成 をクリック。

ステートマシンに名前を付ける。とりあえず、定番の Helloworld で。

ステップ 2: 設計図を選択する

Lambda の結果による分岐ステップを試してみたかったので、 Choice ステート を選択。

ステップ 3: コードとビジュアルワークフローを確認する

ものすごく簡単な Lambda をいくつか作ってみて、 コード の部分にテンプレートとして準備されている JSON をベースに、ワークフローとして設定する。

下記の JSON を入力して、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
{
"Comment": "test",
"StartAt": "hello",
"States": {
"hello": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:hello",
"Next": "how are you"
}
,

"how are you": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:how_are_you",
"Next": "ChoiceState"
}
,

"ChoiceState": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.response",
"StringEquals": "Great",
"Next": "response_good"
},

{
"Variable": "$.response",
"StringEquals": "Not so good",
"Next": "response_bad"
}

],

"Default": "DefaultState"
}
,

"response_good": {
"Type" : "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:response_good",
"Next": "bye"
}
,

"response_bad": {
"Type" : "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:response_bad",
"Next": "bye"
}
,

"DefaultState": {
"Type": "Fail",
"Error": "DefaultStateError",
"Cause": "No Matches!"
}
,

"bye": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:bye",
"End": true
}

}

}

ビジュアルワークフロー の右側にあるリロードアイコンをクリックして、 グラフのプレビューを更新すると、

ちゃんと反映された。

ちなみに、作った Lambda は下記のとおり。

【hello.py】

eventname を受け取り、 hello, <name> と表示して、そのまま name を返す。

1
2
3
4
# hello.py
def lambda_handler(event, context):
print "hello, %s" % event[u'name']
return {u'name': event[u'name']}

【how_are_you.py】

eventname を受け取って、 Bob だったら、 name と、 response として Great を返す。
eventname を受け取って、 Bob 以外だったら、 name と、 response として Not so good を返す。

1
2
3
4
5
6
# how_are_you.py
def lambda_handler(event, context):
if event[u'name'] == 'Bob':
return {u'name': event[u'name'], u'response': u'Great'}
else:
return {u'name': event[u'name'], u'response': u'Not so good'}

【response_good.py】 【response_bad.py】 【bye.py】

それぞれ、固定の文字列を返すだけ。

1
2
3
# response_good.py
def lambda_handler(event, context):
return 'Good!'
1
2
3
# response_bad.py
def lambda_handler(event, context):
return "What's wrong?"
1
2
3
# bye.py
def lambda_handler(event, context):
return 'Bye!'

ステートマシンの作成 をクリックすると、 ステートマシン実行の IAM ロール を指定するダイアログが出てくるので、指定して OK をクリックする。
(ロールがない場合はここで作成)

これだけで、ワークフローが作れてしまった。

コードのポイント

コード の部分に入力するJSONは、 JSON ベースの Amazon ステートメント言語 (ASL) で記述する。

Type

Type として設定できるのは、 Pass Task Choice Wait Succeed Fail Parallel があり、

フィールドとしては上記の表のとおり、設定ができる。
今回は主に、 TaskChoice を使用した。

Task

Task には、 Next もしくは "End": true が必要で、 Next で指定した文字列のタスクが次に実行される。
Resource には、 Lambda の ARN などを指定する。

1
2
3
4
5
"hello": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:hello",
"Next": "how are you"
},

ChoiceState

ChoiceState としては、 StringEqualsBooleanEqualsTimestampGreaterThan などの条件を設定できる。

今回の JSON の ChoiceState の部分では、 Variable$.response を見て、 StringEquals で指定した文字列と一致するかの判別をしている。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"ChoiceState": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.response",
"StringEquals": "Great",
"Next": "response_good"
},
{
"Variable": "$.response",
"StringEquals": "Not so good",
"Next": "response_bad"
}
],
"Default": "DefaultState"
},

Variable として、 $ で結果を受け取ることができる。
例えば、JSON が下記のようなもので結果として渡ってきたら、

1
2
3
4
5
6
7
{
"foo": 123,
"bar": ["a", "b", "c"],
"car": {
"cdr": true
}

}

下記のような形で、値が取得できる。

1
2
3
$.foo => 123
$.bar => ["a", "b", "c"]
$.car.cdr => true

実際に実行してみる

新しい実行 をクリックして、 実行 IDBob を入れ、 event として下記のように設定して、 実行の開始 をクリック。

1
2
3
{
"name": "Bob"
}

無事、実行された。
Bob なので、 response_good の方が実行されているのが分かる。

今度は、 nameTom を入れて実行してみたら、想定どおり response_bad の方が実行され、ちゃんと分岐処理が実行されていることが確認できた。

料金

AWS Step Functions の料金としては、アプリケーションワークフローのあるステップから次のステップに移行すると、状態間を遷移したことになり、 各状態遷移に対して料金が発生する
毎月 4,000 回までの状態遷移は無料で、それ以降は、状態遷移 1,000 回あたり 0.025 USD (状態遷移 1 回あたり 0.000025 USD)となっている。

【参考】
料金 - AWS Step Functions | AWS

まとめ

今回 AWS Step Functions を初めて触ってみたが、比較的簡単にワークフローが作れて、Lambda が管理できることがわかった。
Lambda の制限として、実行時間が5分までというものがあるので、細かい機能で複数の Lambda に分割するケースがよくあると思う。そういった場合に、 AWS Step Functions をうまく活用してやれば管理が楽になりそうなので、社内でも積極的に使っていきたい。

このエントリーをはてなブックマークに追加