こんにちはkubotakです。
今回は弊社で運用・開発しているサービス「M&Aクラウド」の積極買収企業一覧ページの速度改善の話をしたいと思います。 前職でも速度改善プロジェクトをやってましたが、昨今のWebサービスが抱える大きい課題ですね。
まずは今までのアーキテクチャから説明します。
今までのアーキテクチャ
企業一覧ページは検索機能も持っています。 初期表示の全件表示と検索による絞り込み表示が行なえます。
検索するために全文検索エンジン・データベースであるElasticsearch(以下ES)を利用しています。 定期実行バッチによって検索に必要なデータを同期しています。
そして、検索された際にはヒットしたIDの一覧を取得し、そのIDをもとにRDBMSからデータをIN句を利用して取得して表示しています。 つまり、検索用とデータ用は分離しているように見えて、データ取得時には依存関係にあり、分離できていない状態といえます。
また、データの取得処理での速度犠牲として弊社が採用しているLaravelのORMであるEloquentが大きく関わってきます。
Eloquentでは別のテーブルにあるデータをJOINする際に、実際にはSQLでのJOIN句ではなく、データを取得する際に依存しているテーブルにIN句を利用して取得したデータをマッピングします。 先程のESとRDBMSの関係と似てますね。
データが多ければ多いほど取得処理がより遅くなるという仕組みです。
変更したアーキテクチャ
要するにRDMBSのデータを参照せずに、ESから取得したデータだけで画面を生成することができればロスを減らせるというわけですね。 これはCQRSの考え方によるもので、入力するデータと取得するデータのデータベースを分離している状態です。
これを実現するためにはESに画面表示に必要なデータも格納しておく必要があるので、定期実行されるデータ移行バッチを修正して対応しています。 弊社ではある一定の間隔でこのバッチを実行しているのですが、もしリアルタイム性が必要であれば何らかのメッセージングシステムを利用することで実現できると思います。
そして、ESから取得したデータは今まで利用していたドメインロジックを経由することなく、クエリ専用のDTOにマッピングさせて画面で利用しています。
改善後
TTFB(Time to first byte)までの時間が3.32secから679msに改善されました。 現在ページネーションなどを導入せず、すべての要素を表示しているのでまだまだ速度改善としてやれることはありますが、バックエンドの改善だけでも十分な速度改善となりました。
最後に
速度改善だけでなく、一緒にプロダクトを成長させてくれるメンバーを募集しています。