ITの教科書検索
入門読了 約12分

AWS Step Functionsとは ― Lambdaとの違いと再試行

複数のLambdaを順番・分岐・再試行つきで動かすワークフローのサービスです。Lambdaとの違い、RetryとCatch、StandardとExpressの選び方が分かります。

目次
  1. Step Functionsとは
  2. ステートマシンとステート
  3. ステートの種類
  4. Lambdaとの違い
  5. RetryとCatch
  6. タイムアウト
  7. StandardとExpressの違い
  8. 向く場面と向かない場面
  9. 料金の決まり方
  10. 練習問題

AWS Step Functionsとは、処理の順番とやり直しをまとめて管理するサービス

注文の受付・在庫確認・決済・通知をLambdaでつなぐと、途中で失敗したときのやり直しが複雑になります。AWS Step Functionsは、こうした処理の順番・分岐・再試行を定義にまとめるサービスです。各処理は、その定義どおりに動きます。

関数どうしが直接呼び合う作りでは、再試行のコードや進み具合の記録を関数ごとに持つことになります。Step Functionsに任せると、関数には自分の処理だけを書けば済みます。構成図でLambdaの隣にStep Functionsの箱があるときは、Lambdaを動かす順番をそこで決めています。

Lambdaの実行時間は1回15分までなので、長い処理を分けたいときにも使います。まず、ステートの種類とLambdaとの分担を説明します。続いて、RetryとCatchの書き方、StandardとExpressの選び方を取り上げます。

ステートマシンは、ステートをつないだ処理の流れ

Step Functionsでは、処理の流れ全体をステートマシンと呼びます。ワークフローも同じものを指します。流れの中の1つ1つの段階がステートです。ステートマシンを1回動かしたものは、実行と呼びます。

同じステートマシンは、複数の実行を同時に動かせます。注文が10件入れば、同じ定義のまま10個の実行が並んで進みます。それぞれの実行はJSONの入力を受け取り、JSONの出力を返します。

実行の始め方はいくつかあります。コンソールやAPIから始めるほか、Amazon EventBridgeのルールやスケジュールからも始められます。Webからのリクエストで始めたいときは、Amazon API Gatewayを前に置きます。

次の図は、注文を処理するステートマシンの例です。起きることを選ぶと、その実行が通るステートと矢印に色が付きます。定義は1つのままで、実行ごとに通る経路が変わります。

起きることを選ぶ
結果を渡すある成功送信済みないCatch戻したRetry在庫を確認Task1在庫はある?Choice2決済するTask3メールを送るTask4注文完了Succeed5注文を断るFail在庫を戻すTask注文失敗Fail
  1. 在庫を確認するLambdaが動きます。
  2. Choiceが、在庫がある側を選びます。
  3. 決済のLambdaが1回で成功します。
  4. メールを送るLambdaが動きます。
  5. Succeedで実行が終わります。

実行の結果は成功です。

ステートの種類は、処理を実行するTaskと流れを決める7種類

処理を実行するステートはTaskです。残りの7種類は、分岐や待ち時間など、流れそのものを決めます。前の図では、四角い箱がTaskで、両端のとがった箱がChoiceです。

Step Functionsのステートの種類(AWSの開発者ガイドをもとに作成)
ステートすること例
Task1つの処理を実行する。LambdaやほかのAWSサービスを呼ぶ決済のLambdaを動かす
Choice入力の値で次のステートを選ぶ在庫の有無で分ける
Parallel複数の枝を同時に動かし、全部が終わるまで待つ住所と電話番号を同時に調べる
Map配列などの項目ごとに同じ手順を動かす注文の明細ごとに処理する
Wait指定の秒数や日時まで止まる翌朝まで待ってから送る
Pass入力を次へ渡す。固定の値を足すこともできる既定の値を足す
Succeed実行を成功で止める注文を完了にする
Fail実行を失敗で止める在庫切れの注文を断る

Parallelでは、枝の1つでも失敗すると、Parallelのステート全体が失敗します。Taskが呼べるのはLambdaだけではありません。200を超えるAWSサービスのAPIを呼べます。そのため、DynamoDBへの書き込みやSNSへの発行は、関数を作らずに書けます。

ステートマシンの定義は、Amazon States Languageで書きます。JSONをもとにした言語で、略してASLと呼びます。コンソールでは、定義をステートのつながった図として確かめられます。

Lambdaとの違いは、処理を書くか順番を決めるか

Lambdaは、サーバーレスで処理を動かすサービスです。Step Functionsは、処理を動かす順番を管理するサービスです。どちらかを選ぶ関係ではなく、組み合わせて使います。在庫確認や決済の中身をLambda関数に書き、順番と失敗したときの扱いをステートマシンに書きます。

Lambdaが次のLambdaを呼ぶ在庫確認順番と再試行決済順番と再試行通知順番と再試行呼ぶ呼ぶStep Functionsが順に呼ぶステートマシン順番と再試行1番目在庫確認2番目決済3番目通知
色を付けた箱が、順番と再試行を書く場所です。上の作りでは3つの関数に分かれ、下の作りではステートマシンの1か所にまとまります。
LambdaとStep Functionsの違い(AWSの開発者ガイドをもとに作成)
比べる点LambdaStep Functions
書くもの処理のコード順番・分岐・再試行の定義
実行時間の上限1回15分Standardは1年、Expressは5分
どこまで進んだかの記録作る側がコードで持つStandardはステップごとの履歴が残る
料金の単位リクエスト数と実行時間Standardは状態遷移の回数、Expressは実行回数と時間

Step Functionsを使っても、1つのLambda関数の上限は1回15分のままです。15分を超える処理は、段階ごとの関数に分けてつなぎます。

Lambdaにも、複数の手順を再試行つきで最長1年動かせるdurable functionsがあります。こちらは流れをプログラミング言語のコードで書き、Lambdaの中で動かします。使い分けについて、AWSのガイドは次のように勧めています。Lambdaが中心ならdurable functions、複数のAWSサービスをつなぐならStep Functionsです。

エラー処理は、Retryで再試行し、Catchで別の流れへ移す

何も書かないと、1つのステートのエラーで実行全体が失敗します。これを変えるのがRetryとCatchで、Task・Parallel・Mapのステートに書けます。Retryは同じステートをやり直す設定で、Catchは別のステートへ移る設定です。両方を書くと先にRetryを試し、解決しなければCatchへ移ります。

前の図の決済のステートは、ASLでは次のように書けます。Typeがステートの種類で、Nextが次のステートです。ResourceはLambdaを呼ぶ指定で、FunctionNameに動かす関数を書きます。

決済のステートの定義(ASL)
"Pay": {
  "Type": "Task",
  "Resource": "arn:aws:states:::lambda:invoke",
  "Parameters": {
    "FunctionName": "arn:aws:lambda:ap-northeast-1:123456789012:function:pay",
    "Payload.$": "$"
  },
  "TimeoutSeconds": 30,
  "Retry": [{
    "ErrorEquals": ["States.TaskFailed"],
    "IntervalSeconds": 3,
    "MaxAttempts": 3,
    "BackoffRate": 2
  }],
  "Catch": [{
    "ErrorEquals": ["States.ALL"],
    "Next": "RestoreStock"
  }],
  "Next": "SendMail"
}

この定義では、最初の再試行まで3秒待ち、待ち時間を2倍ずつ延ばして3回やり直します。IntervalSecondsが最初の待ち時間で、MaxAttemptsがやり直す回数、BackoffRateが倍率です。省略すると、待ち時間1秒・回数3回・倍率2.0になります。

待つ時間3秒6秒12秒10秒23秒39秒421秒失敗Catchのステートへ移る
丸の数字は何回目の呼び出しかを示し、その下の秒数は最初の呼び出しからの経過時間です。処理そのものにかかる時間は除いて描いています。

ErrorEqualsには、対象にするエラーの名前を書きます。States.TaskFailedは、タイムアウト以外のエラーに一致します。States.ALLは、残りのエラーをまとめて受けるときに最後に書きます。ただし、States.Runtimeのように一致しないエラーもあります。

Retryを書くと、同じ処理が複数回動きます。決済のように二重の実行が問題になる処理では、同じ注文を二度処理しないよう関数の側で防ぎます。Standardの実行が失敗で終わっても、14日以内なら失敗したステップから再開できます。この機能をredriveと呼びます。成功済みのステップはやり直しません。

タイムアウトを書かないと、応答を待ち続けることがある

TaskのTimeoutSecondsは、そのステートが動いてよい最大の秒数です。超えるとStates.Timeoutのエラーになり、RetryやCatchの対象にできます。ステートマシン全体にも、同じ名前の項目で上限を書けます。

APIを呼んですぐ次へ進むTaskには、既定のタイムアウトがあります。一方で、ジョブの完了や外部からの通知を待つTaskには既定のタイムアウトがありません。応答が来なければ、実行の上限まで待ち続けます。AWSのベストプラクティスも、Taskごとに妥当なタイムアウトを書くよう勧めています。

StandardとExpressの違いは、長く確実に動かすか、短く大量に動かすか

ステートマシンを作るときは、ワークフローの種類をStandardかExpressから選びます。既定はStandardで、作成後は変更できません。長く動き、1回だけ確実に実行したい処理にはStandardが向きます。短い処理を大量に回すならExpressが向きます。

StandardとExpressの違い(AWSの開発者ガイドをもとに作成)
比べる点StandardExpress
実行時間の上限1年5分
実行の回数の保証1回だけ。Retryを書いた分はやり直す非同期は少なくとも1回、同期は多くて1回
料金の単位状態遷移の回数実行回数と、実行時間とメモリ
実行の履歴APIとコンソールで90日間見られるCloudWatch Logsへのログを有効にして見る
完了の通知を待つ呼び出し使える使えない
向く処理決済や人の承認を含む処理IoTデータの取り込みなど大量で短い処理

Expressには非同期と同期の2つの動かし方があります。非同期は開始の確認だけを返します。同じ実行が2回以上動くことがあるので、2回動いても結果が変わらない処理に使います。同期は、終わるまで待って結果を返します。途中でエラーになっても、その実行をやり直しません。

人の承認を待つ処理はStandardで作ります。Standardなら、タスクトークンという識別子が返ってくるまでTaskを止めておけます。Expressはこの待ち方を使えず、実行も5分までなので、数日待つ処理は作れません。2つを組み合わせる形もあります。AWSのベストプラクティスが挙げる例では、決済や承認をStandardに残します。在庫の更新のようにやり直せる処理は、Expressに切り出します。

Step Functionsが向く場面と向かない場面

次のような処理に向きます。

  • 注文処理のように、順番どおりに進み、途中で分岐や再試行がある処理
  • 人の承認や外部のシステムの完了を待ち、数時間から数日かかる処理
  • 複数のサービスを順に呼ぶ処理。マイクロサービスの間の流れもここに入ります
  • どのステップまで進んだかを、あとから確かめる必要がある処理

次のような処理には別の方法が合います。

  • 1つの関数で終わる処理は、Lambdaだけで足ります
  • 処理の依頼をためておき、あとで順に片付けるだけなら、Amazon SQSのキューで足ります
  • 同じ通知を複数の相手に配るだけなら、Amazon SNSのトピックで足ります

SQSとの違いは、進み具合を誰が持つかにあります。Step Functionsは、各ステップの状態を記録します。SQSで流れを作ると、進み具合の管理はアプリの側に残ります。

大きなデータの受け渡しには注意が要ります。ステートの入出力の上限は256 KiBなので、大きなデータはAmazon S3に置き、場所だけを渡します。Standardの1回の実行の履歴にも25,000件の上限があり、超えると実行が失敗します。

料金は、Standardが状態遷移の回数、Expressが実行回数と時間で決まる

Standardの料金は、状態遷移の回数で決まります。状態遷移は、ワークフローのステップを実行するたびに数える回数です。Retryのやり直しも1回ずつ加わります。無料枠は月4,000回で、12か月の無料期間が過ぎても続きます。

AWSの料金ページには、米国東部(バージニア北部)で1回$0.000025の例があります。開始と終了を含めて4回遷移するワークフローを月10万回動かすと、40万回です。無料枠を引いた396,000回分で、月$9.90になります。

Expressの料金は、実行の回数と実行時間で決まります。実行時間は100ミリ秒単位で切り上げ、使ったメモリは64 MB単位で数えます。どちらの種類でも、呼び出したLambdaなどの料金は別にかかります。単価は2026年10月31日に確認した値です。最新の値はAWSの料金ページで確認してください。

参考にした資料

練習問題(全4問)

Q1AWS LambdaとAWS Step Functionsの関係として正しいものはどれ?
Q2TaskのステートにRetryもCatchも書いていないとき、そのステートでエラーが起きるとどうなる?
Q31つのTaskにRetryとCatchの両方を書いた。エラーが起きたときの順番として正しいものはどれ?
Q4決済を含む注文処理で、担当者の承認を数日待つことがある。向くワークフローはどれ?

選んでから「採点する」を押すと、解説つきで答え合わせができます。

関連記事

AWSの記事を続けて読む

AWS 全38本中12本目