こんにちは。メディアドゥでシニアエンジニア・スクラムマスターを担当している濱口です。
本記事では、大規模な電子書店システムに対して、いかにしてマイクロサービス導入を進めたのかを解説しています。
用語解説
・MDCMS-SD
電子書店を構築・運用するための機能を提供する電子書店ウェブサイトの構築システム。100以上の電子書店検索から決済まで提供。
・配信サービス
数あるコンテンツを電子書店向けにまとめ、オンラインで配信するシステム。200万点以上のコンテンツ、7万件/秒の配信処理。
MDCMS-SDについて
MDCMS-SDができあがったのは2011年で、元々のアーキテクチャは以下のようになっていました。md-dcという電子書籍における取次全般の機能を提供する大きなシステムがあり、そこで配信やレコメンド機能が提供されていました。
このmd-dcによって、電子書店における配信部分の提供が可能でした。システム開発を自前で行わなくても電子書店を立ち上げたいというニーズを満たすためにMDCMS-SDがあります。このMDCMS-SDではウェブサイトの表示やアカウント機能、決済機能などが提供されます。
そして2020年に、アーキテクチャが以下のように変更されています。md-dcからeBookというシステムに変わっています。eBookには配信機能がなかったので、別途配信サービスという形で新しいサービスも立ち上げています。
このアーキテクチャ変更に伴って、以下のようなミッションが必要になりました。これらの開発を約1年(実質半年)で行う必要がありました。
- 100書店分の連携先切り替え
- 書籍データの連携・購入・閲覧の仕組み変更
- レコメンド機能の自前実装
MDCMS-SD状況分析
当時のMDCMS-SDは以下のような状況でした。
元々のJavaとPHPで書かれたプログラムを改修しても良いのですが、ざっと単純計算で見積もると求められる期日に対して、現実的ではない工数がかかるのが分かりました。その解決の糸口として、色々なトレンドの技術をキャッチアップすることにしました。そうした中で、某社の技術カンファレンスが開催されており、そこで出会ったのがマイクロサービスになります。
現状のシステムを改修するとなると、途方もない工数がかかり、開発期間も読めない状況です。社内ではJavaを修正するだけじゃないかという意見もありましたが、マイクロサービスとして開発することでゼロベースで考えられるようになります。そうすることで既存のコードに対する影響を考えずに、何を作れば良いかが明確になります。開発期間に影響しそうな点としては、新しく習得しようとする技術の学習速度くらいかなと前向きに考えていました。
このような見積もりの比較を経て、解決策として検討したのが以下の4つになります。
ストラングラーパターン
システムの振る舞いは変更せずに裏側の実装を入れ替える方法です。例えばREST APIの仕様は変更せずに、裏側を変えるといった具合です。現状と同じ仕様のものを別に立てて、接続先を変えるだけで新しいシステムが使えると言ったパターンになります。
修正ではなく新規
md-dc互換のシステムを開発して、MDCMS-SD本体には手を入れない作戦としました。
技術選定の変更
新しく作る部分はインフラや言語を大胆に変更しようと考えました。
スクラム開発
私自身がスクラムマスターのライセンスを持っていますので、その知見を活かしてチームの活動と完了までの進捗や残タスクの可視化をしようと考えました。
技術選定
メディアドゥでは配信サービスにAWSを使い始めており、すでに稼働して実績を上げ始めていました。そうした中で、メディアドゥとしても全社的にAWSを使っていこうという流れがありましたので、本件でもAWSを活用しようと考え、AWSでコンテナを使っていくことにしました。
プログラミング言語としては配信サービスでも利用しているGo言語を採用しています。メディアドゥはGoに力を入れており、Go Conferenceという国内のGoコミュニティを中心とした技術カンファレンスにスポンサーとして、何回か登壇させてもらっています。
後は既存システムがPostgreSQLを利用しているのに対して、NoSQLを利用してみようとDynamoDBを採用しています。社内的には、これがDynamoDBを採用した最初の事例になります。
整理すると、md-dcがなくなった部分を埋める形でブリッジシステムを作る形になっています(以下の画像参照)。そうすることで、システムの互換性を保ったまま、本体(MDCMS-SD)に手を加えずに修正できると考えました。
戦略
実際にどう進めていくかの戦略は以下のように考えました。
まずmd-dcを利用する書店と、配信サービスを利用する書店が共存できる形で進めています。すでに切り替えている書店もありますが、一部はまだmd-dcを使い続けているというのをMDCMS-SDを窓口として扱いながら、裏側では共存できるようにロードマップを書いています。
ブリッジのシステムはサーバーやバッチが殆どになるのですが、go modulesは役割毎に分ける形にしました。ちょうどその頃、クリーンアーキテクチャに関する情報が書籍やネットにたくさんあったので、それを参考としています。責務の違うプログラムはモジュールごと分離しましょうというのを少人数ながら行っています。
後はモジュールが分かれていれば、個別にデプロイが行えます。例えば書籍を購入する部分と、購入した書籍を閲覧する、サンプル書籍を閲覧するといった部分を分離しておくといった具合です。それぞれスケーリングも異なり、個別にデプロイできれば修正が別の機能に影響を及ぼさなくなります。そうすることで影響を掌握できます。
データ移行については「まとめて」と「イベント発火」に分散しています。
まとめて移行
数十万コンテンツを扱っている書店さんが100書店くらいあります。その商品情報をmd-dc版から配信サービス版に一気に切り替えます。これは両立が難しいものなので、まとめて一気に移行させます。
イベント発火
「あるコンテンツをあるユーザーの方が買いました」といった購入履歴データは、コンテンツのマスターデータよりも量があります。10年近くサービス運用していますので、購入履歴の数はとても多く、一部では億単位のレコード数があります。
そのため、特定のタイミングでメンテナンスに切り替えて全て移行するというのは現実的ではありません。そこで、コンテンツを読むイベント時に、移行したかどうかを判定します。もし移行していなければ、配信サービス側でも読めるようにオンライン上での処理でデータを移行しています。
このように商品情報総入れ替えと、購入履歴のオンラインでの順次入れ替えという戦略をとっていました。
レコメンドについて
次にレコメンドについてです。元々レコメンドはmd-dcで提供していました。中のソースコードを細かく見たわけではありませんが、集合知プログラミングを参考に独自実装されていたようです。そのレコメンドを、前述したような実装を行いながらチーム4人で実装するのは難しかったです。そこで解決策として、Amazon Personalizeを導入してみようと言う話になりました。
Amazon Personalizeは機械学習を用いたレコメンド用サービスになります。このAmazon Personalizeを使えば複雑なロジックを実装することなくレコメンデーションが実現可能です。当時は、リリースされてから2〜3ヶ月しか経っていなかったのですが、新しいものを導入していこうという方針だったこともあり、採用することにしました。結果として、Amazon Personalizeを導入して成功したと思います。AWSのブログでも事例として紹介されています。
【お客様事例】株式会社メディアドゥ様 Amazon Personalize 電子書店システムへの活用 | Amazon Web Services ブログ
最終的なアーキテクチャ
最終的にまとめますと、以下のようなアーキテクチャになりました。
CMSブリッジと呼んでいるブリッジシステムのソースコードはGitHub上管理しています。CI/CD周り、デプロイ自動化やユニットテスト自動化などは徹底的に行っており、AWSへのデプロイまではかなり自動化されたCI/CDが汲まれています。その先ではECSで典型的なサーバーレスパターン(またはコンテナパターン)となっています。
サムネイルリサイズサービスというのは電子書籍の書影を生成するサービスです。MDCMS-SDでは書影をトップページで表示したり、アプリでは大きく表示すると言った際に、1個の画像をリサイズして提供しています。最近ではCDNの裏側でリサイズを行ってくれるものもあったのですが、すべて切り替えることはできませんでした。1個の書影・サムネイルを複数サイズにリサイズするところではコンテナを使ってスケールの力で行っています。
後は価格やタイトル、説明文などをまとめて書誌データと呼ぶのですが、そういった電子書籍の書誌データを取り込んで本体のデータベースに流す処理もあります。この書誌データはmd-dcから提供していたものと、配信サービスから提供されるものとでデータ形式がかなり変わってしまっています。そのため、取り込むために複雑なロジックを挟んでいます。
他にも書籍の購入や買った書籍の配信については、元々md-dcが7万リクエスト/秒処理していましたので、そのブリッジを開発しています。レコメンドについては、前述の通りです。ギリギリDockerは使っているけれど、マイクロサービスといえばマイクロサービスかなといった構成になっています。
サーバーレスのデータ保存やファイル保存はAmazon S3やDynamoDBを使いながら、レコメンドではAmazon Personalizeを利用しています。こうしたサービス群をMDCMS-SD本体から呼び出したり、逆にマイクロサービス側から本体のストレージや、PostgreSQLにデータを書き込むと言ったことを行っています。
※この記事は12月9日に行われたサブカル業界Developers 勉強会 Vol.3にて行われたセッションの内容を書き起こした記事です