前提
下記の記事でバッチ処理はLambda契機のHTTP通信で実行するようにしていました。
ざっくりの流れ
EventBridge -> Lambda -> HTTPリクエストでECSのバッチ処理を起動
しかし、バッチ処理に時間がかかるようになり、CloudFrontのレスポンスタイムアウト30秒内にレスポンスを返せなくなってきて、Lambdaにてタイムアウトエラーが発生するようになってきました。
ECS内では無事にバッチ処理は完遂していますが、実行元のLambdaにレスポンスだけ返せていないという状況です。
CloudFrontのレスポンスタイムアウトを変更するのはWebアプリケーション全体に影響が出てしまうし、Maxは60秒で付け焼き刃感が否めないので、今回はECSのスケジュールされたタスクというものを使用してみることにしました。
全体の流れ
- cron 基準で時間になったらECSタスクが1台起動する
- 仕込まれていたバッチ起動コマンドをECSタスクが実行する
- バッチ実行を完了したらタスクが終了する
- この間web用のタスクは常時起動している
- バッチ実行中はWeb用とバッチ用でタスクが複数台になるイメージ
設定方法
ECS -> クラスター -> スケジュールされたタスク から設定
-
スケジュールされたルールの名前:任意
-
スケジュールされたルールの説明:任意
-
スケジュールされたルール:ON
-
スケジュールされたルールのタイプ:cron式
- e.g. 毎日0:10に起動させる場合:
cron(10 15 * * ? *)
- e.g. 毎日0:10に起動させる場合:
-
ターゲットID:任意
-
起動タイプ:FARGATE
-
プラットフォームバージョン:LATEST
-
タスク定義ファミリー:任意
-
タスク定義のリビジョン:最新(空白にすることで最新リビジョンになる)
-
タスクの数:1
-
VPC:任意(Web用タスクと同じもの)
-
サブネット:任意(Web用タスクと同じもの)
-
セキュリティグループ:任意(Web用タスクと同じもの)
-
パブリックIP:ON
-
タスクロール:上書きは特になし
-
このターゲットのEventBridge IAM ロール:空白 (ecsEventsRole というルールが自動生成される)
-
コンテナの上書き
- e.g.:
bundle,exec,rails,runner,Batch::Daily.execute
- 実行したいバッチ処理を起動するコマンドを入力する
- e.g.:
動作確認
DBのログ確認
logs テーブルにて日時バッチと15分毎のバッチのログが記録されている。
タスク実行まで cron の時間から2分程度誤差がある模様。リアルタイム性は求めていないので許容範囲でしょう。
アプリケーションのログ確認
アプリケーションログはS3に保管されており、検索にAthenaを使っている。
Athneaでrails用コンテナのログを検索する。
スケジュールタスク用のコンテナが立ち上がってバッチ処理を完遂していることを確認。
起動している台数とかも考えなくていいし、スケジュールドタスクめちゃめちゃ便利じゃ!!!!!!🎉🎉🎉