こんにちは、プロダクト部・エンジニアの今井です。
TANP(タンプ)では、データの連携・加工・抽出や、ユーザーへのお知らせ配信など、多様な用途でバッチ処理を活用しています。特に、メール配信を目的とするバッチ処理が多く存在しており、これらの管理や運用に関連する多くの課題を抱えていました。本記事では、これらの課題を解決するための過程やどのように技術選定を行ったのかについて書こうと思います。
バッチ処理に関連する課題
バッチ処理はプロダクトが成長し続ける中で広く利用され、数も増えてしまいますが、その管理が不十分だと課題もモリモリ増えていくことになります。実際に私たちは以下のような課題に直面していました。
【コード管理できていない部分がある】
特にインフラの設定についてはコード管理できていない部分が多くありました。再現性低く、管理の手間やインフラリソース全体の設定の見通しが低い状態になっていました。
【デプロイの整備が行われていない】
過去にサクッと作られた小さなバッチなどを含めて、共通のデプロイ設定やバッチによっては自動デプロイが組まれていないものもあり、これもまた管理が煩雑になる原因になっていました。
【webアプリケーション用のEC2インスタンスに相乗りしているバッチがある】
バッチの起動中はCPUやメモリなどのリソースを消費してしまうことがあり、アプリケーションのパフォーマンスが低下してしまう可能性がありました。
【EC2、ECS、Lambdaといった異なるサービス(アーキテクチャ)で動作している】
新しくバッチを追加する際のルールやテンプレートが整備できておらず、様々なサービスを利用したバッチが乱立してしまい管理が煩雑になっていました。
なぜメールの基盤を作ることになったのか
冒頭で触れたような課題を抱えており、ビジネス的な要件が増加・変化する中で、今後さらに増えるであろうバッチ処理を効率良く整理し、追加や運用のコストを削減する必要があることから、バッチ周りの整備に着手しました。
解決の第一歩として、「用途」、「サービス」、「処理時間」、「DBの参照」、「外部サービスとの連携」といった要素を軸にして、現状のバッチ処理を整理することから始めました。
画像を見ていただいてもお分かりいただけるかもしれませんが、メール送信を行うバッチが特に多いことに気づきました。
検討の結果、メール送信周りの仕組みを整えることで、他のバッチ処理も効率良く管理できるようになると考え、まずはメールの基盤整備から手を付けることにしました。
メール基盤における技術選定について
メール基盤を構築するにあたっては、バッチ処理の課題解決だけではなく、以下のようなメール周りの仕様や課題の解決も考慮しつつ設計を行いました。
- バッチ処理によるメール送信だけではなく、ユーザー操作などによる都度のメール送信にも対応できるようにする
- 似たようなメールのテンプレートを各アプリケーションで重複して管理している状態を解消する
- 送信済みメールの本文をアーカイブして参照できるようにする
これらを踏まえて、以下のような構成でメール基盤を整えることにしました。都合上省略している部分もありますが、大まかな処理フローをイメージいただけると思います。
構成全体については、課題の解決を前提とした上で、今後のメンテナンスコストやスケールの容易性に焦点を当てた技術選定を行いました。言語やサービスについては以下のような基準で選定を行いました。
Go
概要図のLambda部分の実装にはGo言語を採用しました。選定にあたっては、Dockerイメージを軽量に作成でき、(Lambdaの)起動速度を高めることができることや、言語として後方互換性が高く、メンテナンスコストを抑えられることから、この決定をしました。
また、バッチひとつひとつが独立しており、小さく導入を開始できることもGo言語を採用する後押しとなりました。弊社ではサーバーサイドの言語としてPHPを採用することが多いですが、構成・運用上のメリット等を示せば、比較的新しい技術の導入や技術的な挑戦に対しても寛容な環境だと思います。
Lambda
アプリケーションの実行環境としてLambdaを選択しました。ECS(Fargate)の利用も検討しましたが、「対象の抽出」、「メール本文の構築」、「メールの送信」といったそれぞれのステップが15分以内に完了するため、最終的にLambdaを使用することになりました。
さらにLambdaは再実行がしやすいことや、各関数(バッチ)が独立してスケールでき、管理するリソースを最小限に抑えることができる点も選定の上で重要なポイントでした。
DynamoDB
Lambdaと費用面での相性が良く、高いスケーラビリティを持つことからDynamoDBを選択し、メールの送信情報などの管理を行う方針としました。
さらに、TTLを設定することで有効期間を過ぎたデータ項目を自動的に削除することができ、ストレージコストの管理やデータのライフサイクル管理を手間を省くことができる点も重視しました。
SQS
イベントリレーにはSQSを採用しました。SQSの高い耐障害性やLambdaと組み合わせの相性が良いことが選定理由です。概要図では省略していますがデッドレターキューを設定しているため、エラー解析等が容易になり、Datadogと組み合わせてアラートや監視にも役立てています。
デプロイ
Lambdaのデプロイにはfujiwara/lambrollを使用し、GitHub Actionsを活用してCDを組んでいます。プルリクエストのマージをトリガーとしてデプロイが行われます。
また、EventBridgeなどのインフラリソースについてはTerraformを用いてコードベースで管理しています。
また、メール基盤を作成し、処理を集約することで、メール周りの変更を容易に実施できるようになることにも期待ができます。具体的には、これまで各アプリケーションで個別に管理されていたメールライブラリのバージョン管理が不要になることや、現在はSendGridを使用していますが、将来的にAmazon SESに切り替える必要が生じた場合も、より少ない工数での変更が可能になります。
まとめ
プロダクトの成長を見据えて、現状の課題を整理し、より良いサービスを一緒に作っていけるメンバーを募集しています。
少しでも興味を持っていただけた方はタンプの各種募集記事からお気軽にご連絡ください!お待ちしております!
エンジニア採用サイト:https://tanp.jp/company/engineer/