Aidemy の第2期リファクタリングを 2021年11月~12月に実施しました。
リファクタリングの主要な効果は、表題の通りデータベース(DB)をAzure Cosmos DB から Mongo Atlas on GCP に移管して API 速度を210%以上改善したことです。(*1 測定条件は末尾に記載)
DB移管は起案から実現まで紆余曲折あり2年間にわたったプロジェクトで、大きな効果が出たことを大変嬉しく思います。
今回のリファクタリングは上記を含め以下の3つの大きなテーマがありました。
- DB移管
- 開発体制の整備
- 管理画面表示スピードUP
それぞれについて振り返ります。
リファクタリングの目標と実績は以下の通りです。DB移管だけでなく各項目で当初の目標を満足することができました!
テーマ | 目標 | 結果 |
---|---|---|
DB 移管 | DB 費用削減 > 50% | 50% 減 |
DB 移管 | リソースを GCP に集約 | 達成 |
開発体制の整備 | ビルド時間削減 > 50% | 60% 減 |
開発体制の整備 | イメージ ID の手動割当の廃止 | 達成 |
管理画面の表示速度 UP | 進捗一覧 API 時間削減 > 20% | 20% 減 |
DB移管
Aidemyでは開発リソースを Google Cloud Platform (以下、GCP) に一元化することを目指し、順次移行を進めてきました。リファクタリング以前のシステムでは、データベースのみMicrosoft Azure (以下、Azure) のデータベースを利用していました。データベースもGCPに移行することでほとんどのリソースを一元化することができます。
また利用していたAzureのデータベース (Cosmos DB mongoapi) は高機能で、かなり高コストとなっていたため、コストの削減を目指しました。
Azure -> GCP と異なるパブリッククラウド間で移管するということで、移管前後のデータに互換性を持たせられるか、データ移管のフローなど慎重に検討しました。 初めの構想では、Aidemyのサービスが成熟してきたこともあり、以下の観点からRDBへの移管を目指していました。
- 複数コレクション間にまたがる情報を一度に取得したい
- ーブル構成を壊したくない (NoSQLだと自由にデータを格納できるため、ドキュメントが壊れる可能性がありました)
しかし、NoSQL -> RBD は構成が異なるため移行するための工数が膨大にかかるのと、検証が非常に緻密さが求められること、さらにアプリケーション側のロジックにも改善の余地があったため、エンジニアで何度も議論・検証し、NoSQLのままで移行することに決めました。
選定したMongo Atlasは、サービス自体はMongodbが提供していて、実行するサーバをAzure,AWS,GCPから選べる形式でした。GCPへリソースを集約したかったことと、アクセスに応じて自動スケーリング機能を有していること、そしてバックアップ機能も充実していたため、Mongo Atlas に決定しました。
検証の結果、DBのクエリはCosmosDBに比べ、countのクエリは40%程度、updateは3~5倍速くなっています。
また移行前準備として、mongoのモデル操作ツールとして利用していた mongoose のバージョンアップも行いました。v3 -> v4のメジャーアップデートをしたため、クエリの変更など多岐に渡りましたが、セキュリティ向上のため一気に対応しました。
データ移管では Azure Data Factory というツールを使いました。こちらのツールは、接続文字列さえ入力できればパブリッククラウドの垣根なく移管できる優れものです。移管前/移管後のデータに整合性があるかどうかもチェックでき、移管作業は非常に楽にできました。
移管作業そのものは深夜メンテナンスで3時間程度で終わりましたが、起案、検討、実装、検証前準備含めて2年にもわたる大規模プロジェクトで、完了したときには非常に感慨深いものがありました。
開発体制の整備
開発時やデプロイ用のイメージ作成の際、ビルド時間がかなりかかることで作業時間が削られ、リリースまでの時間に短縮余地がありました。ビルド時間を高速化することで、開発効率の向上を図りました。 開発能率の向上にあわせて、更新の止まったライブラリ(gulp-typescript)およびgulp自体への依存を解消しています。 Aidemyのデプロイフローでは、サービスデプロイ前にGithub のタグを切り、そのタグをDocker Imageのタグに割り当てる運用をとっていました。しかしタグ切りが手動だったため、ヒューマンエラーによる不具合が起きてしまっていました。ヒューマンエラーを排除するため、仕組みで解決を目指しました。
開発能率の向上と、更新の止まったライブラリ(gulp-typescript)への依存解消を目的に、ビルド工程のリプレースを実施しました。 ビルドツールはesbuildを、linterには eslint_dを採用しました。結果、CircleCIで両工程の合計所要時間が98sから38sに6割削減されています。 エンジニアが平均10回/日ほどデプロイ作業を実施していると考えると、一人あたり5時間/月の工数削減効果が見込めます。
またイメージの手動タグ切り廃止では、まず理想のデプロイ方式についてエンジニア全体でMTGを行いました。そのMTGの中で、各commitでユニークな値かつ自動で付与される値ということで「コミットハッシュ」を利用することにしました。 circleciのjob上でcommitからコミットハッシュを取得し、イメージタグに付与するようにしました。 手動を完全に排除できたのでヒューマンエラーを低減できたのと、手動作業による工数が減りました。
管理画面表示スピードUP
Aidemyのサービスで時間がかかる機能の一つに「進捗一覧表示」があります。この進捗一覧ロジックには並列化できる箇所が含まれていました。1) DB移管 でクエリ速度の改善が見込まれたため、合わせてロジックも改善することでより高速な管理画面を目指しました。結果として500人のチームで時間の20%短縮に成功しました。
サービスの利用者様が使いやすいシステム作成を今後も目指します!
*1. [測定条件] Aidemy Business Cloud のメンバーが10,000名存在するチームを想定して計測しました。