こんにちは。LINEヤフー株式会社で、出前館というプロダクトのサーバーサイドエンジニアをしている古田大志です。
株式会社出前館はLINEヤフーのグループ会社です。 資本業務提携を結んでいて、LINEヤフーが開発などをサポートしています。
詳しくはこちらをご参照ください。(https://corporate.demae-can.co.jp/pr/news/demaecan/line.html)(外部サイト)
今回の記事では、その出前館における開発の内容を紹介させていただきます。
出前館はデリバリーサービス事業のプロダクトで、開発においてはマイクロサービスアーキテクチャを採用しています。出前館のマイクロサービスの1つに、クーポンに関するドメインの責務を持ったコンポーネントであるクーポンサービスがあります。
クーポンサービスでは、ビジネスエンハンスに伴う「非機能要件の増大」や「仕様の複雑さの肥大化」という課題に対して、「イベント駆動のインフラアーキテクチャ」や「ドメインの凝集度や完全性を意識したアプリケーションアーキテクチャ」を採用し開発を進めてきました。本記事ではそれらの技術的工夫について紹介したいと思います。
なお、過去には出前館のマイクロサービスに関する記事や、クーポンサービスに関する記事などもあるので、そちらもぜひご参照ください。
- 20年以上続くフードデリバリーサービス「出前館」におけるマイクロサービス化の取り組み(漆原, Tech-Verse 2022)
- 出前館 マイクロサービスにおける加盟店管理画面のBFFアーキテクチャ(古田, LINE KYOTO交流会 2022)(外部サイト)
- 出前館クーポンサービスでのサーバーアプリケーションのSpring Boot 3系対応
- Amazon ECSにおけるカナリアリリースの実現
クーポンサービスとは
クーポンサービスとは、出前館内のクーポン機能のデータなどを管理するバックエンドのシステムです。
出前館におけるクーポンとは、「1500円以上買ったら送料310円」「新規会員のみ500円off」など値引きを行う機能のことです。これらエンドユーザーに提供しているクーポンは、裏側の業務としては、出前館がマーケティング施策としてクーポンを作ったり、出店している加盟店がキャンペーンとしてクーポンを登録したりすることによって、データが作成されています。クーポンサービスでは、このさまざまなactorに対するデータフローの中心に立ち、データの管理や処理を行っています。
その他にも、出前館におけるクーポンは、ビジネス要件を達成するためにさまざまな属性を持っています。
例を挙げると
- 使えるユーザーの区分を限定する「初回ユーザー専用 / 誰でも利用可能」
- 使える加盟店の区分を限定する「店舗指定 / どの店舗でも利用可能」
- 値引きの対象を指定する「商品金額値引き / 送料金額値引き」
- 誰がお金を出したかの区分を管理する「加盟店原資 / 出前館原資」
など、さまざまなパラメータを設定することができます。また単純なenumなどでは表現できないようなビジネスロジックもたくさんあります。
これらの表現豊かな仕様が、開発における実装の複雑さを上げています。
イベント駆動アーキテクチャについて
出前館のクーポンドメインにおける仕様の複雑さに、「クーポンの枚数の変更」や「注文時のクーポン利用」など、エンドユーザーの行動がトリガーとなってクーポンの状態に変化が起きることが挙げられます。出前館のアクティブユーザーは、数百万のオーダーに上っていて、それに付随してクーポンに関するデータの更新系/参照系に関する非機能要件も大きくなっています。また、クーポンという特性上、キャンペーンや配信に伴いエンドユーザーのアクセスが一時的に増え、開発側が想定していないようなトラフィックが発生することがあります。
例えばトラフィックがコントロールできないほど大きくなり、律速しにくい場合に関して、更新系の場合は適切なトランザクション処理をできなくなるかもしれないといった懸念があります。また、アクセスの多いデータに関しては、Redisなどを用いてキャッシュするのがレスポンス高速化の方法の1つとして挙げられますが、このキャッシュするデータのライフサイクルも更新が多いものに関しては気をつける必要が出てきます。
これらのような更新系/参照系の課題を解決するために、クーポンサービスの開発ではイベント駆動のインフラアーキテクチャを採用しています。具体的には、ユーザーへクーポンを付与するという事象や、ユーザーの注文時のクーポン利用、またデータの変更によるユーザー用キャッシュデータへの反映などを全てイベントとして取り扱い、Apache Kafkaというメッセージキューを利用して非同 期化して処理フローを構築しています。
一例としてクーポンを利用するユースケースでのデータフローの図を示します。
このように、各処理の受け渡しを、同期的なAPI処理ではなくイベント連携の形式で非同期で行うことにより、更新系の律速を出前館のシステム側が主体で行うことができ、トランザクションなどの処理が失敗しないようにしています。また、メッセージキューを使うことでデータ連携の可用性を高めることができています。
また、上記の例で挙げた図では、注文イベントをproduceするのはクーポンサービスとは別のシステムで、出前館内の他のマイクロサービスが担っています。 このように異なるチームのシステム間もイベント連携することで、consumeする側が必要な情報のみを受け取ることが可能になっているのも1つのメリットと言えます。
ドメインモデルの完全性について
クーポンサービスというマイクロサービス内では、上記で挙げたような非同期のイベントを処理するsubscriber以外に、同期的なapi処理や、定期的なbatch処理のユースケースもあります。言語は Java 17, フレームワークは Spring Boot 3.0 で実装されていて、ランタイムとしてはapi/batch/subscriberの3種類のアプリケーションをモノレポで取り扱っています。
下記は実際のディレクトリ構成の図です。