時間のかかる処理でLambdaを使うのを止めた

以前、こちらこちらの記事でLambdaに関する技術情報を取り上げました。その時に開発していたWebシステムを改修することになり、現在対応しているのですが、このシステムのとある処理が、Lambdaだとどうしても不都合があり、Lambdaなしで作り直すことにした、という話です。

経緯

今回修正するのは、サーバ上のデータベースに蓄積されたデータを、期間を指定して集計する処理です。大量のデータを扱うため、指定する期間が短ければ数秒で終わる処理ですが、期間が長くなると場合によっては数分~数十分かかる、非常に重い処理となります。そのため、この集計処理をジョブとしてキューに登録し、バッググラウンドプロセスで処理する構成を検討していました。大体以下の図のような感じです。

では、どのようにジョブを処理していくか。そこが課題となりました。

このような構成であれば、通常はキューに登録されるジョブを監視する、デーモンやサービスなど常駐型のアーキテクチャを採用するのが正攻法な気がしますが、 当時は、オートスケーリングが必要になるのを見据えてサーバーレスで開発するのが基本方針でしたので、AWS Lambdaで開発することにしました。

しかし、Lambdaはイベント駆動型のアプリケーション実行アーキテクチャです。一応、cronのような定期実行の仕組み(EventBridge)はあるため、それも検討しましたが、粒度が残念ながら分単位であるため、数秒で終わるジョブでも最大1分待たされるケースが出てきてしまう、という事で採用を断念。結果的に、以下の構成で実装することになりました。

システムのサーバサイドを担うWebAPIとしてのLambdaと、集計を実行するLambdaの2つを用意し、いずれもHTTPリクエストを実行トリガーとして登録。WebAPIのジョブ登録機能の処理の最後に、もう1つのLambdaを実行するHTTPリクエストを非同期で実行することで、バックグラウンドプロセスで集計処理が開始される、という所謂メッセージ型の仕組みです。

この構成で実装を完了し、システムの試用運転を開始しました。

発生した問題と解決策

試用運転開始後、いくつかの不具合が挙がってきましたが、そのうちのいくつかは、上記の構成およびLambdaの仕様に起因するものでした。

  • 負荷が集中すると、集計処理に失敗する場合がある。
  • 集計期間が半年以上となる集計処理に失敗する。

実装のどこかにミスがあるのか、一度に大量の集計リクエストが発生すると、ジョブが途中で停止してしまうようでした。また、Lambdaにはタイムアウト上限が15分という制限があり、集計期間が半年を超えると集計処理が15分を超えてしまうようで、この場合もジョブが停止してしまうようでした。

この問題への対応を検討した結果、Lambdaによる実装は諦め、EC2インスタンス上に常駐型のジョブ監視デーモンを置くことにしました。オートスケーリングの設定が面倒になる等のデメリットもありますが、確実に集計処理が動作することを優先した形になります。

最終的な構成はこちらの図の通りとなりました。

所感

AWS、特にLambdaを開発業務で利用するようになってまだ半年程度ですが、サーバーレスの向き不向きや使いどころが少しづつ分かってきた気がします。今回のような、時間のかかる処理はサーバーレスコンピューティングに向かない処理の1つのようです。

コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA