Aws+SpringBoot上での定期実行の実装方法検討
EC2⁺SpringBootで動いているWebアプリで定期実行機能を実装することになり、
何を使って実装するかについて検討を行ったのですが、
思ったより色々な方法があったので、備忘も兼ねてメモしておきます。
やりたかったこと
トランザクションデータについて毎日深夜にチェックを行い
対応期日が近いにも関わらず未処理なデータを抽出して警告フラグを立てる。
前提
- データはRDS(Aurora)に格納されている。
- トランザクションデータ量は現状月間数百件と少ない。
- 小規模な社内用システムなので、EC2は冗長構成になっていない。
- 処理は対象レコードをSQLで抽出してUpdateするだけ。
ようするに、小さなシステムでのささやかな日次処理です。
候補として考えた/調べたもの
- AwsBatch
- AwsLambda
- Spring上で何とかする
検討結果
AWSBatch
https://aws.amazon.com/jp/batch/
利用できなくはないものの、明らかにオーバースペックでした。
EC2インスタンスを大量に立て、その上で大規模データを分散処理するためのフレームワークなので、
ちょっとした処理を日次で回したいためだけに使うのは不適切です。
AWS Lambda + CloudWatch
大した処理ではないのだからサーバーレスで行こうという発想です。
LambdaとAuroraは相性が悪いとよく言われます。
しかし、これはlambdaのトリガーとなるイベントの数が制御できない場合に
大量同時起動によってコネクションが枯渇する恐れがあるためです。
よって、今回のように一日深夜に一回だけというケースでは問題になりません。
実装方法としてはlambdaを適当な言語で書いて、
CloudWatchのスケジューリング型のルールにターゲットとして紐づけてやるだけなので大した手間はありません。
有力な候補です。
Spring上で何とかする
この辺りまで考えて、そもそも現在の構成で定期実行機構を外に出す必要があるのかという疑問も出てきました。
現在のこの社内システムはユーザーがごく少数で、リソースには余裕があります。(深夜はなおさら)
何となく流行りのアーキテクチャということで外に出しそうとしていましたが、
モノリスティックな構成で制御可能な範囲ならそちらの方が楽なケースは多々ありますし、
分割する必然性はありません。
というわけで、すでに立っているEC2上で処理してしまう方法を考えます。
SpringBatchかSchedulingTaskか
cronで何かを叩かせてもいいですが、せっかく同じサーバー上で実行するからには
Spring上で行ったほうがロジックの再利用性や管理の面で便利です。
Springでバッチ系処理というとSpringBatchが有名ですが、
AwsBatchほどではないにしても、大規模で複雑なデータ処理用に高度に抽象化された基盤です。
今回の日次のちょっとした処理には依然としてハイスペックすぎます。
一方で、SchedulingTaskなら少し依存性を足してアノテーションを付けるだけで定期実行可能です。
https://spring.io/guides/gs/scheduling-tasks/
cron書式で指定できるので、当然日次実行も問題ありません。
というわけで、今回の目的のためには一番これが楽そうです。
スケールアウトが必要になったらどうするのか?
APサーバーとバッチ処理を密結合させてしまうことの最大の問題点は、
APサーバーを冗長構成にしたりスケールアウトさせた場合の実行制御が難しくなることです。
(普通にそのまま2台、3台と増やしてしまうと多重実行されてしまう)
今回検討しているシステムについてはそこまで拡大する予定がないので問題はないと思いますが、
万が一必要になった場合には、ロジックをWebAPIから呼び出す形に変えて、
AWSLambdaに叩かせるように変更しようと思います。
まとめ
- ちょっとした定期実行処理ならSpring上でSchedulingTaskが楽。
- スケールアウトが必要にならばlambdaで。
- AWSBatchはビッグデータの分析等に