Share
Embed
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
2026/9/5 (土) - 9/6 (日) 開催の「JAWS SONIC 2026」にて登壇した資料。
イベントページ
https://jawssonic2026.jaws-ug.jp/timetable/niigata
kasacchiful PRO
September 05, 2026
Transcript
39 slides
-
自己紹介 笠原 宏 (@kasacchiful) クラスメソッド株式会社 データ事業本部 ビジネスソリューション部 ソリューションアーキテクト 新潟県新潟市在住 JAWS-UG新潟
/ Python機械学習勉強会 in 新潟 / JaSST Niigata / ASTER / SWANII / Cloudflare Meetup Niigata / AI CRAFT Hacks Niigata / KomeKaigi AWS Community Builder (Serverless) 2022, 2025 Japan AWS Top Engineer / 2022-2026 Japan All AWS Certifications Engineer AWS Samurai 2025 2 -
今日のお話 AWS Step Functionsを使って、大規模並列実行する際の心構え 1. イベント履歴 25,000 の壁と、分割ワークフローでの回避 2. 分割したワークフロー間での、データの受け渡し
3. Mapステートで並列数を上げきる 4. 並列数を上げた先で考慮すべきこと 3 -
クイズ Lambda を呼んで、Choice で判定して、まだなら戻る。 それだけのループです。 Standard ワークフロー (ステートマシン) の最大実行時 間は1年です。
さて、Lambda関数は何回ループ実行され るでしょうか? A. 約25,000回 B. 約5,000回 C. 約3,500回 D. 上限なし(1年動き続ける) 4 -
最大実行イベント履歴 25,000 イベント Standard Express 最大実行時間 1年 5分 最大実行履歴サイズ 25,000イベント
無制限 イベント履歴の上限を超えるとステートマ シンの実行が失敗します 上限解放不可 (ハードクォータ) Express は無制限 履歴を Step Functions 側に持たず CloudWatch Logs で持つため https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/service-quotas.html 7 -
イベント履歴 24,999 からの挙動 公式ドキュメントより AWS Step Functionsの実行イベント履歴には 25,000 エントリのハードクォータがあり ます。実行イベントが
24,999 件に達すると、次のイベントが発生するまで待機しま す。 イベント番号 25,000 が ExecutionSucceeded の場合、実行は正常に終了します。 イベント番号 25,000 が ExecutionSucceeded 以外の場合、ExecutionFailed イベント はログに記録され、履歴の上限に達したためステートマシンの実行は失敗します。 https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/sfn-best-practices.html 8 -
状態遷移と実行イベント {% $count < $iterations %} 状態遷移 実⾏イベント Start Pass
state Task state (Lambda Invoke) Choice state ExecutionStarted PassStateEntered TaskStateEntered ChoiceStateEntered PassStateExited LambdaFunctionScheduled ChoiceStateExited Succed state End ExecutionFailed LambdaFunctionStarted LambdaFunctionsSucceeded TaskStateExited ループは Lambda関数実行のTaskステートとChoiceステートを順に繰り返したので、 1ループあたり「2つの状態遷移」/「7つの実行イベント」が発生。 Starndardワークフローの課金対象は「状態遷移数」(今回は 7145 ) なので、実行イベントは あまり気にしないことが多いが、大規模実行の場合は実行イベントも気にする必要がある。 9 -
実行結果 Start 1イベント × 1回 ( ExecutionStart ) EventHistoryInit (Pass
state) 2イベント × 1回 EventHistoryInvokeCounter (Lambda Invoke) 5イベント × 3571回 EventHistoryCheckDone (Choice state) 2イベント × 3570回 + 1イベント 24999イベント目が ChoiceStateEntered End 1イベント × 1回 ( ExecutionFailed ) 実行イベント: 1+2+(5×3571)+(2×3570+1)+1 = 25000 10 -
回避方法 — ステートマシンの実行を分割する 履歴は「ステートマシンの実行単位」でカウントされる。 つまり、ステートマシンの実行を分ければ回避可能。 ステートマシンの実行を数珠繋ぎで ステートマシンの実行を入れ子で 公式ドキュメント上でも以下の記載があり、この方法を推奨している。 ワークフローをより小さなステートマシンに分割し、進行中の作業を新しい実行で継続 する必要があります。
入れ子構造で分割・実行するケースが多いので、以降「分割 = 入れ子」で記載します。 https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/tutorial-continue-new.html 11 -
入れ子の書き方 { "Type": "Task", "Resource": "arn:aws:states:::states:startExecution.sync:2", "Arguments": { "StateMachineArn": "arn:aws:states:...:stateMachine:ChildWorkflow",
"Input": { "AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID": "{% $states.context.Execution.Id %}" } } } Resource startExecution startExecution.sync startExecution.sync:2 挙動 起動して即座に次へ。完了を待たない 完了を待つ。結果は「エスケープされた文字列」 完了を待つ。結果は「パース済み JSON」 入れ子したい部分をTaskステートで子ステートマシンを呼び出す。同期実行であれば、結果 を親ステートマシン側に返せる。 12 -
親子をリンクさせる AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ に親の実行IDを付与すると、コンソールで 「親から子の実行ステートマシンへ」リンク が張られます。 親の実行IDを付与しなくても動作するが、付 与しないとこのリンクは出ない CDK なら associateWithParent:
true で 自動付与可能 ステートマシンを分割すると追跡が難しく なるので、必ず付与したい ID 13 -
ワークフロー分割後に考える問題 - データの受け渡し ワークフロー分割した後、今度はワークフロー間のデータの受け渡しを考える。 子ワークフローに何を渡し、子ワークフローから何を受け取るのか。 ステートの入出力は 256 KiBまで UTF-8エンコードされた文字列として 上限解放不可
(ハードクォータ) Standard / Express 共通 ステート間の入出力 (ペイロード) のサイズをうまく調整してあげる必要がある。 15 -
データフローシミュレータ コンソールのデータフローシミュレータは、 JSONPathの入出力処理5段階を1つずつ評価し て前後の JSON を並べてくれます。 現在は、非推奨 データフローシミュレータページは メンテナンスされなくなりました。… JSONATA
クエリ言語をサポートしてい ません。 推奨は Workflow Studio の「テスト状態」/ TestState API。 17 -
JSONata なら、入出力処理が5つから2つになる 入力側 出力側 変数 JSONPath + Parameters ResultSelector +
ResultPath + OutputPath Assign で保存、後続で参照可能 InputPath JSONata Arguments Output Assign で保存、後続で参照可能 JSONPathよりシンプルに処理できる。 QueryLanguage はステート単位で指定可能 既存はそのままJSONPathで、新しく書くステートからJSONataにすることが可能 Assign した変数は入出力ペイロードに載せずに渡せる 単一変数最大サイズ: 256 KiB / 1実行あたりの全変数合計: 10 MiB 別ステートマシンには変数は渡らない (スコープ外) 18 -
同じ子ワークフローを3,000個起動したいときは? Mapステートを使って子ワークフローを並列処理するのが王道 シンプルな処理では、Distributed Mapで並列実行数を簡単に引き上げることが可能 観点 同時実行数 実行履歴 入力 256KiB制限 Map
最大 40 程度 Mapステートを管理する親ワークフローに残る JSON配列のみ 受ける Distributed Map 最大10,000 「マップ実行」として独立して持つ JSON配列 / S3(CSV, JSON, JSONL, Parquet ほか) S3 から直接読む場合は回避可能 「S3バケット内の特定のパス配下にある全ファイルを処理する」ケースだと、Distributed Mapがシンプルかつ強力な武器となる。 20 -
子の起動速度は、ワークフローの種別で変わる Distributed Map の⼦ワークフロー起動速度(実測) 6秒 3,000件 30秒 2,500 2,000 凡例
1,500 実測 約550/秒(公称 up to 1,000 TPS) Express ⼦ Standard ⼦ 実測 ちょうど100/秒(公称 100 TPS) 1,000 500 0 0 5 10 15 20 到達点は同じ3,000。違うのは、そこまでの速さ 25 30秒 24 -
ワークフロー種別毎の起動速度比較 子の種別 公称 実測(3,000件) Express up to 1,000 TPS 6秒(約500件/秒)
Standard 100 TPS 30秒(100件/秒) Standard は30秒間ぴたりと毎秒100件。 Express は公称「最大 1,000 TPS」に対して、実測値は約半分程度。 25 -
Distributed Mapの子ワークフローへの入出力 で各子に渡す入力を組み立てる JSONata が使える 大きなデータはペイロードに載せず、S3 のキーだけ渡して子ワークフロー側で読み込む ResultWriter で結果を S3
に書き出す 親ワークフローに集約しなくて済む あわせて設定しておきたいもの。 ItemSelector ItemBatcher 複数アイテムをまとめて1つの子に渡す。起動回数が減る ToleratedFailurePercentage エラー許容率。指定した割合までのエラーを許容してMap全体を成功として扱える。 既定だと 1件失敗した時点で他も中断される 26 -
実際に 3,000 並列実行してみた結果 確認事項 Step Functions 側の子実行 Lambda 最大同時実行数 Lambda
スロットリング 全体の所要時間 結果 3,000件すべて起動完了 1,500(上限緩和して 1,500 にしている状態) 8,273回 265秒 所要時間の理想は 60秒くらい (3,000×30秒÷1,500) だが、実際には 約4.4倍時間がかかった 28 -
壁は下流に移る 並列数を上げると、サービスクォータの壁は下流側のサービスに移っていく When using a distributed map, be sure to
verify the quota on downstream services. — Distributed Map 発表ブログ https://aws.amazon.com/blogs/aws/step-functions-distributed-map-a-serverless-solution-for-large-scale-parallel-data-processing/ 30 -
並列実行数を上げた際に気になる Lambda の制限 壁 値 1 同時実行数 既定 1,000 /
リージョン 2 スケール速度 1,000インスタンス / 10秒 / 関数 3 リクエスト速度 10,000 req/s 引き上げ 可 不可 不可 通常はあまり気にしない同時実行スケーリングレートだが、並列実行数を上げるとスロット リング発生につながる 公式ドキュメントの理解度テストの例がわかりやすい。 平均20ms の関数で 30,000 req/s を捌きたい。同時実行数は 30,000 × 0.02 = 600 で 足りそう。 しかし 10,000 req/s の上限に引っかかるので、同時実行数を3,000以上に上げる申請が 必要。 https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-concurrency.html 31 -
Step Functions 自身のクォータも確認しておく オープン状態の Map 実行の最大数: 1,000 Distributed Mapに適用 /
ハードクォータ 超えた分は MapRunStarted イベントで待機される StartExecution API にもスロットリングがあり リージョンによって値が異なる 上限緩和可能 1.でイベント履歴 25,000 を回避するために入れ子ワークフローにしたが、その入れ子は StartExecution APIを呼んでいる。公式ドキュメントの通り、スロットリングに対応するた めに Retry を設定しておく方が良い。 Retry で StepFunctions.ExecutionLimitExceeded を使用して、実行が確実に開始さ れるようにします。 https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-nested-workflows.html 32 -
MaxConcurrency で制御する 同じ処理を MaxConcurrency: 1500 に絞って実行してみた。 3000 最大同時実行数 1,500 Throttles
8,273 所要時間 265秒 1500 1,500 0 128秒 最大同時実行数を絞ったら Throttles がゼロになり、しかも2倍以上速くなった! 上限を超えて投げても、下流が受け取れなければ Retry の往復が増えるだけ。 並列度は上げれば上げるほど良い、わけではないことに注意。 33 -
まとめ Standard の実行履歴は 25,000イベントまで 履歴は「実行単位」 入れ子に分割すれば、各ワークフローで実行履歴 25,000イベントまで対応できる。 分割したら次はデータの受け渡し 必要な値だけをうまく入出力できるようにしておくこと。 Distributed
Map は入れ子をシンプルに利用可能 子の起動速度は Express と Standard で5倍以上違う。 並列を上げるとサービスクォータの壁は下流に移る 特に各サービスのスケーリングや最大実行数に注意が必要。 上限緩和できるかどうかも確認しておく。 スロットリング対策として Retry 設定しておくと良い。冪等性の担保を忘れずに。 MaxConcurrency で制御する 最大実行数を絞ったほうが速いこともある 35 -
今後のJAWS-UG新潟 2026/9/16 (水) JAWS-UG新潟#33 AWSサポートが言いたいセキュリ ティサービスあるあるPart2 AWS Expert Online for
JAWS-UG #39 2026/10/03 (土) JAWS-UG新潟#34 AWS Step Functionsハンズオン 2026/12 頃 AWS re:Invent 2026 re:Cap (予定) 他、毎週木曜夜21時からオンラインで「プチキャッチア ップ会」も開催中! 詳細・参加申込は connpass ページをご確認ください。 37 -
参考リンク Step Functions service quotas(AWS Docs) Best practices — Starting
new executions to avoid reaching the history quota Start workflow executions from a task state(入れ子ワークフロー) Transforming data with JSONata in Step Functions Map workflow state Understanding Lambda function scaling Step Functions Distributed Map(発表ブログ) 39