ワードサジェスト検索機能をGoogle CloudとElastic Cloudを使ってリアーキテクトしました

サムネイル

はじめに

こんにちは!データ基盤開発部ML基盤チームの河西です。

私達のチームでは、DMM.comの数百万を超えるコンテンツを情報検索や機械学習を使ってユーザーにパーソナライズして届けるために、検索・レコメンドの改善を行うMLエンジニアと協業し、日々MLバッチ基盤の改善を行っています。

また、MLバッチ基盤とは別に、ユーザーリクエストに対して学習された結果をレスポンスする、ユーザーフェイシングなAPI基盤の開発・改善も同時に行っています。

今回はそんな中でも、ユーザーが検索した際に検索キーワードがサジェストされる、ワードサジェストサービスをリアーキテクトしたプロジェクトの紹介をしたいと思います。

こちらの記事では、以下について紹介をします。

  • Google Cloud及びElastic Cloud利用した検索システムの構築
    • 検索及びインデキシング

以下の事柄については割愛します

  • Elasticsearchのindex設計

プロジェクトの背景

検索ワードのサジェストは、DMM.com各ページの上部にある以下のようなテキストボックスから入力した際に利用されるサービスです。

従来こちらの検索には以下のような問題がありました。

カテゴリによる絞り込み

検索ではカテゴリ(電子書籍や通販など)を選択できますが、現行の検索エンジンであるSolrの設計がカテゴリを考慮した設計になっておらず、選択されたカテゴリに応じたワードではなく、カテゴリ外であっても同一のワードがサジェストされるようになっています。

例えばPCゲームを検索した際、PCゲームカテゴリに作品が存在しなくとも、カテゴリ外に同様の名称のものがあればサジェストされてしまい、実際に検索するとヒット数が0件になってしまうといった挙動です。

そのため、ユーザー体験としては良いとは言えず、改善する必要がありました。

クライアントとの通信

一方で、クライアントとバックエンドサーバー間の通信はクロスドメインで通信をしており、対応策としてJSONPを利用していました。しかしながら、JSONPは昨今推奨される一般的な通信方法ではありません。

そのため、CORSを利用してXHRやFetchAPIといった通信への切り替えを検討する必要があります。

JSONPやCORSの詳細については、以下を参照ください。

https://en.wikipedia.org/wiki/JSONP

https://en.wikipedia.org/wiki/Cross-origin_resource_sharing

以上から、indexingするためのバッチジョブ及び検索API両面において、リアーキテクトを検討しました。

次は、検討した内容についてです。

構成の検討

ここで、現行の構成について軽く触れておきます。

API基盤・Job基盤と記載してある部分が私達のチームが持っているプロダクトとなり、両基盤ともAWSのEKSで動いています。

すでに現行の構成を構築したメンバーはおらず、設計ドキュメント等は残っているもののSolrの再設計を含め、課題解決するためにはコストが高い(≒新規作成したほうが良い)状態でした。

※簡略化のために省略していますが、Job基盤はS3やK8sの様々なコンポーネントをイベント駆動的に組み合わせ実現しているため、キャッチアップや改修・調査などにも時間を要していました。

こうした背景もあり、構成を検討するにあたってポイントになった点は以下です。

  • 全社のデータ基盤がGoogle CloudのBigQueryに集約されており、Google Cloudへ移行した場合の親和性が高い
    • 特にマルチクラウドな運用においては、OIDC設定などの権限管理が不要になる点も大きい
  • API、Job基盤共に、セルフホストしている部分の管理工数が大きく、マネージドなサービスに寄せていきたい
    • 不要なリソース管理をやめつつ、できるだけシンプルな構成を目指す

以上のような点から、Google Cloudを実行基盤にすることとしました。

構成

最終的には以下のような構成となりました。

API基盤

API実行基盤にはCloud Runサービスを利用し、LoadBalancerを経由したアクセスのみに絞っています。

LoadBalancerには、Cloud CDNやCloud Armorポリシーを付与することで、パフォーマンスやセキュリティに対して担保しています。

また、Elastic Cloudとの通信に関してはDirect VPC Egress + Private Service Connectを利用し、Elastic Cloudのホストに対してのみVPCを経由してアクセスするようにしています。

これにより、インターネットに公開することなく疎通することが可能となります。

詳細についてはGoogle Cloud及び、elasticのドキュメントを参照いただければと思います。

https://cloud.google.com/vpc/docs/private-service-connect?hl=ja

https://cloud.google.com/run/docs/configuring/vpc-direct-vpc?hl=ja

https://www.elastic.co/guide/en/cloud/current/ec-traffic-filtering-psc.html

Job基盤

Job基盤は、バッチフロー全体を管理するためのCloud Run Jobsと、インデキシングするためのDataflowジョブに分かれています。理由については後述します。

Cloud Run JobsはCloud Runサービスに対して、バッチ実行に特化したサービスです。また、Direct VPC Egress等ネットワーク設定はAPI側と同様の設定ができるため、リソースの設定や構成の使いまわしができる点も大きいです。

一方でDataflowはマネージドなETLサービスで、オートスケールにより効率的なリソース管理ができるほか、後述するテンプレートのみで実行できるので、インフラリソースを意識する必要はありません。

パイプライン開発にはApache Beam SDKが利用できるため、GoやPython等のプログラミング言語を利用して、パイプラインを作成することができます。

本プロジェクトではパイプラインのテンプレートを実装しましたが、それ以外にもGoogleが提供しているユースケースに応じたテンプレートが複数あるため、必要に応じて使い分けできると良さそうです。

EKS Job基盤のパイプラインと比較し、インフラリソースの管理が不要になった点と、複数のJobを組み合わせてインデキシングしていた構成から1つのテンプレートのみで管理できるようになった点で、管理・開発コスト共に非常に良くなりました。

新しい構成に関しては、開発当初はDataflowのみを利用してインデキシングを行っていましたが、その際APIのレイテンシが悪化し、性能要件を満たせない事象が発生したため、構成図に記載の通り、検索とインデキシングのインデックスを切り離して処理をすることで対応しました。

余談ですが、現時点(2024/05)では、Elastic CloudはCPUやメモリ等のリソースに応じたオートスケールがないため、バッチであればcron等で処理するスクリプト、リアルタイムであればメトリクス等をトリガーに処理するスクリプトを自身で設計する必要があります。

まとめ

DMMで利用されるワードサジェストサービスのリアーキテクトについて紹介しました。

今回は、セルフホストからマネージドサービスによるリアーキテクトを行いました。

それぞれの開発や運用に関しては、どちらも一長一短があると思います。

その時の状況やユースケースに応じて適切に判断していく事が必要だと改めて感じました。

そして、Google CloudやElastic Cloudは今後も様々なサービスの提供が予定されているため、それらを利用してパーソナライズ化を加速させていきます。