AWS Step Functions導入によるバッチ処理の改善
はじめまして。出前館 エンジニアの石井と申します。
普段はサーバーサイドエンジニアとして、出前館に加盟いただいた飲食店様向けの各種レポート機能(以下、加盟店レポート )を担当しています。
その中で、今回バッチ処理のアーキテクチャ改善について携わる機会がありましたので記事にしたいと思います。
導入した背景
―加盟店レポートのアーキテクチャ
加盟店レポートとは、各店舗毎に売上高や売れ筋の商品等をまとめたレポート情報のことです。
加盟店レポートは加盟店の担当者様がPCやタブレットのブラウザ等からSPAのアプリを通じてアクセスできるようになっており、作りとしては、AWSクラウド上に各種アプリケーションをデプロイし稼働させることでこれを実現しています。
潜在的な課題
加盟店レポートでは、レポート情報の種類毎にバッチの処理単位を分けそれぞれをECSの1Taskとして切り出して管理しています。
各Taskは、元データの加工やレポート情報の整形のために5~10件程度のテーブルに対しCRUDを行っています。こうした中、加盟店レポートのアーキテクチャは以下の問題を抱えていました。
―①バッチの本数が多い
レポート情報の加工や整形の都合上、Task間には依存関係が存在しTaskAを実行した後にTaskBを実行する必要がある等といった運用上の制約が存在します。
加盟店レポートでは、レポート情報の作成に必要なバッチが9本(日次7本、月次2本)存在しており、更に新規で2本追加が必要となっている状況でした。
合計すると11本で、このタイミングでバッチの管理体系について見直しをする必要がありました。
―②バッチの依存関係をスケジュール実行の時間で管理している
既存のアーキテクチャでは、実行順序の管理をする代わりにEventBridgeのRuleでTaskの起動時間を細かく設定することで、運用上の制約を満たしています。(具体的には、各Taskの実行時間から逆算して24時にTaskAを実行→25時にTaskBを実行、等といった形。)
そのため、バッチがスケジュール通りに完了しないと依存関係が崩れてしまいます。
―③依存先のバッチ実行が失敗した際、後続バッチが誤動作するおそれがある
各バッチは互いに依存関係があるにも関わらず、依存先のバッチの実行結果を知る術がありません。そのため、あるバッチの実行時に依存先のバッチ実行が失敗してもそのまま後続バッチが実行されるつくりとなっています。
結果的に、障害時は後続バッチを一時停止する等の人力のオペレーションが必要という状況になっていました。
―④起動したいバッチ(ECS Task)の数だけEventBridgeのRuleが増える
①の都合上、各バッチを順番に実行するためにはECS Taskの数だけRuleを設定する必要があります。このため、バッチをまとめて管理すれば本来不要となるようなRuleまで作成しているという状況になっています。
検討したこと
上記課題を解決するために、ジョブネット(≒バッチの依存関係を定義したもの)という概念を導入し、バッチを複数単位で管理する方法について検討しました。
この実現手段として、既存のアーキテクチャをベースにした場合大きく分けて2つの方針が考えられます。
方針 | ①ジョブネットをアプリ側で実現する | ②ジョブネットをインフラ(AWS)側で実現する |
---|---|---|
概要 | アプリのフレームワーク等の機能を使いジョブネットを実現する | AWS Batch、AWS Step Functions等を使ってジョブネットを実現する |
メリット | 細かい所までカスタマイズできる | アプリ側の改修が不要 ECS Taskをそのまま使い回すことができる |
デメリット | アプリの改修が必要になるジョブネットによりバッチ実行単位が変わるためインフラ側の変更も必要となる | AWSサービスの内容次第では意図した処理フローが実現できない可能性がある |
検討した結果、比較的容易に実現できそうな方針②を採用することとしました。
利用するAWSサービスに関しては、下記理由によりAWS Step Functions(以下、Step Functionsと表記)を採用することにしました。
- エラー通知、リトライ処理等も含め、ワークフローを細かく設定できる
- GUIベースでジョブネットの管理や実行ができる
- 連携できるAWSサービスが豊富で、拡張性が高い
Step Functionsの導入
―導入イメージ
Step Functionsは、ステートという単位で処理を管理し一連の処理フロー(以下、ワークフローと表記)を制御するAWSのサービスです。ワークフローはステートマシンと呼ばれるリソースで定義され、1つのワークフローにつき1ステートマシンという形になります。
ステートマシンは文字通り状態遷移図を表し、Amazon States LanguageというJSONベースの言語で以下の内容を定義できます。
- 各ステートでどういうアクションを行うか(ECS Taskを実行する、SNSに通知を送る等)い
- 各ステートはどういうフローで実行されるか(並列、分岐、繰り返し、待機等)い
ステートマシンで定義したワークフローはAWSのコンソールからGUIベースで確認し、簡単に実行することができます。(実行結果も画面から確認可。)
―作成するリソース一覧
Step Functions導入にあたり、最低限下記のAWSリソースを作成する必要があります。
AWSサービス | リソース | リソース |
---|---|---|
CloudWatch | ロググループ | ステートマシンのログ出力用 |
CloudWatch | Eventのルール | ステートマシンのスケジュール実行用 |
CloudWatch | Eventのターゲット | ステートマシンのスケジュール実行用 |
AWS IAM | IAMロール | ステートマシン用 ▼紐づくIAMポリシー ・ロググループへの参照 ・アクセス権限 ECSまわりの権限(ECS Taskの実行等) |
AWS IAM | IAMロール | Eventのターゲット用 ▼紐づくIAMポリシー ・ステートマシンの実行権限 |
Step Functions | ステートマシン | ECS Task実行用 ※ワークフローを定義するJSONも別途作成 |
上記リソースは全てTerraformで扱うことができるので、今回は全てTerraform化してコードで管理することとしました。
Step Functionsを導入した結果
ジョブネットの構成について検討しそれをStep Functions化した結果、下記のように構成が変わりました。
バッチ処理を日次と月次の2つに分け日次用のステートマシンと月次用のステートマシンを作成し、それぞれでバッチの依存関係を管理する形としています。
各ステートマシン内でワークフローを定義したため、バッチの依存関係をビジュアルで(≒AWSのコンソールで)把握できるようになりました。
Step Functionsを導入して嬉しかったポイント
―①バッチをまとめて簡単に実行できる
AWSの画面から、複数のバッチをまとめて簡単に実行できるようになりました。ステートマシンでバッチの依存関係は整理されているため、正しい実行順序を守りながらバッチ実行を行うことができます。
以前だと、複数バッチを実行するためには1つ1つ手動で実行して結果を確認し次のバッチを実行するという手順を踏む必要があり、作業者が長時間張り付く必要がありました。これがボタンひとつでいけるようになったのは大きいです。
―②画面からバッチの実行結果、ログ、実行時間が見れる
Step Functionsのステートマシンの実行結果のページから各バッチ(ECS Task)の実行結果を確認できるようになりました。これにより、どのバッチが成功してどのバッチが失敗したか、またその時にかかった時間や出力されたログ等も確認することができます。
―③バッチ同士の依存関係が管理しやすくなる
AWSの画面からステートマシンのワークフローを確認することで、バッチ同士の依存関係が一目でわかるようになりました。ステートマシンにバッチを追加する際もWorkflow StudioというGUIのツールベースで手軽に行えるため、修正も簡単です。
―④既存リソース(ECS Task)が使いまわせる
元々運用していたバッチのECS Taskをそのまま素材として、ステートマシンから使いまわすことができました。勿論アプリケーションのソースコードの変更はなく、ECS Taskも修正もなしで再利用できたため、比較的短時間でジョブネットの構築が可能です。
―⑤不要なEventBridgeのリソースを破棄できる
バッチの数だけ存在していたスケジュール実行用のEventBridgeのリソースを最小限に減らすことができました。以前だと、どのバッチが何時に実行されるといった確認が必要だったのですが、スケジュール実行が日次と月次で1つずつとシンプルになったためその手間が省けるようになりました。
―⑥複数バッチの実行時間を最適化できる
各バッチのトリガーをスケジュール実行からフロー制御の形に変えたため、バッチとバッチの間の余計な待ち時間を省いた形でバッチ実行を制御できるようになりました。
Step Functionsの活用シーン
今回のように、
- AWS上に既存の資産(アプリケーション、インフラ等)を活用したい
- 複雑化したバッチの依存関係をシンプルにまとめたい
- 複数の処理単位をボタン一つでまとめて実行したい
といった要件がある場合は、Step Functionsの導入を検討する価値があると思います。手軽に導入できるわりに享受できるメリットも大きいですし、Step Functionsには下記のような強みもあり拡張性にも優れています。
細かいフロー制御ができる | LambdaからLambdaを実行する、LambdaからECS Taskを実行する、etc... |
---|---|
上記のWorkflow Studioの他、2021年10月のアップデートで200以上のAWSサービスを組み込めるようになった | 参考:ローコード開発ツール「AWS Step Functions」が大幅拡充、200以上のAWSサービスを組み合わせたクラウドアプリ開発が容易に - Publickey |
加盟店レポートにおいても、今後更なる機能追加を予定しておりますので、引き続きStep Functionsを活用したアーキテクチャ等を検討していこうと思っています。
以上、皆様の参考になれば幸いです。