Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ZOZO基幹システムリプレイスの歩み ~マイクロサービス?モジュラモノリス?~ / ZOZO ...

takumi.okamoto
July 24, 2024
230

ZOZO基幹システムリプレイスの歩み ~マイクロサービス?モジュラモノリス?~ / ZOZO BackOffice System Replacement Project History

2004年のZOZOTOWNサービス提供開始以来、ZOZOの基幹システムはモノリシックなアーキテクチャで成長してきましたが、2022年より障害の分離と開発生産性向上を目指し、分散・疎結合な基幹システムを目指すリプレイスプロジェクトを開始しました。本セッションでは、入荷機能をモジュラモノリスへ移行した事例・発送機能をマイクロサービス化した事例を紹介します。

takumi.okamoto

July 24, 2024
Tweet

Transcript

  1. © ZOZO, Inc. 株式会社ZOZO 基幹システム本部 物流開発部 基幹リプレイスブロック 岡本 拓実 2020年4月に株式会社ZOZOに新卒入社

    レガシー環境での開発・運用を経て 現在はリプレイスプロジェクトに従事 趣味は不要不急の買い物で散財すること 2
  2. © ZOZO, Inc. 3 アジェンダ • ZOZO基幹システムのこれまで • ZOZO基幹システムリプレイスプロジェクト発足 •

    事例① 入荷機能のモジュラモノリス基盤への移行 • 事例② 発送機能のマイクロサービスへの移行 • おわりに
  3. © ZOZO, Inc. 5 ZOZO基幹システムとは 経理 商品管理 カスタマー サポート 発送

    入荷 在庫棚卸 セール 設定 etc ZOZOの社員やZOZOTOWN出店者様が利用するバックオフィス業務のためのシステム全般
  4. © ZOZO, Inc. オンプレミス 6 ZOZO基幹システムの歴史 モノリス (Webアプリケーション) 定期実行バッチ 定期実行バッチ

    定期実行バッチ トランザクション スクリプト トランザクション スクリプト トランザクション スクリプト ストアド プロシージャ ストアド プロシージャ ストアド プロシージャ 2004年からZOZOTOWNの成長と共に大きなアーキテクチャ変更なく進化してきた 開発規模 基幹DB VBScript VBScript およそ 12チーム/80人 + α Microsoft SQL Server
  5. © ZOZO, Inc. 7 ZOZO基幹システムの抱える課題 開発生産性の低下 • 技術のレガシー化 • 複雑に絡み合ったトランザクションスクリプト形式で影響範囲がわかりづらい

    • 自動テスト(テストツール自体)が存在せず、大規模なリファクタリングの実施は博打 に近い • 改修する度に変更容易性と開発体験が悪化しがち(良くて現状維持) 障害リスクの増大 • 基幹DBが単一障害点でありDBのパフォーマンスが全ての機能に影響する • 慢性的に発生するエラーや手動クエリ実行による補正など
  6. © ZOZO, Inc. 9 基幹システムリプレイスの要件整理 Must • レガシー化した技術を一新する • (ドメイン駆動設計を武器に)ドメインモデル形式へ移行してモジュール性を高める

    • 日常的なリファクタリングを前提とした改善し続けるシステムにする • オブザーバビリティを獲得し健全に運用する • (基幹DBのパフォーマンスチューニングにさらに注力) Nice to have • マイクロサービス化(主にDB分離による障害分離の観点で)
  7. © ZOZO, Inc. 11 基幹システムリプレイスの現状 物流領域が最もリプレイスの優先度が高いため物流領域から着手 • 事例① 入荷機能のモジュラモノリス基盤への移行 •

    事例② 出荷機能のマイクロサービスへの移行 新物流拠点で稼働するマテハン機器(物流機器) 出典: ミライをソウゾウする物流拠点「ZOZOBASEつくば3」(ZOZO公式Youtube)
  8. © ZOZO, Inc. モノリス モノリス 13 モノリスからモジュラモノリスへ モジュラモノリス View Logic

    View Logic Web API Before After API化 モジュール化 DB分割 マイクロ サービス化? 安定した境界を見つけるまで試行錯誤する 停止期間 なしで移行 Step.1 Step.2 Step.3 Step.4 を意識しつつ徐々にモジュール性を手にいれる ・Web APIのインターフェース ・レイヤー構成とその依存関係 「後から変更しづらい部分」
  9. © ZOZO, Inc. 14 モノリスからモジュラモノリスへ モジュラモノリス Logic Web API API化

    モジュール化 DB分割 マイクロ サービス化? 安定した境界を見つけるまで試行錯誤する Step.1 Step.2 Step.3 Step.4 を意識しつつ徐々にモジュール性を手にいれる ・Web APIのインターフェース ・レイヤー構成とその依存関係 「後から変更しづらい部分」 モノリス モノリス モジュラモノリス View Logic View Logic Web API Before After 停止期間 なしで移行 出展: 杉本啓 「データモデリングでドメ インを駆動する ――分散/疎結合な基幹 系システムに向けて」 (技術評論社) 出展: @98lerr「EventStormingをやってみた話」(Qiita)
  10. © ZOZO, Inc. 15 モジュラモノリス基盤について① • 基幹DBにアクセスする • Java・Spring Boot

    • Gradleマルチプロジェクト・単一のWeb APIアプリケーション • 基本的にはZOZOTOWNリプレイスと同様のインフラ構成※ ◦ AWS EKS ◦ 内製API Gateway・Istio ◦ Datadog・Sentry・PagerDuty ◦ アプリ用リポジトリとインフラ用リポジトリを分離/GitOps ついに最強のCI/CDが完成した 〜巨大リポジトリで各チームが独立して・安全に・高速にリリースする〜(ZOZO TECH BLOG) CIOpsからGitOpsへ。Flux2でマイクロサービスのデプロイを爆速にした話(ZOZO TECH BLOG) あのサービスの監視・オブザーバビリティ アーキテクチャ選定【前編】(Findy Tools 開発ツールレビューサイト) 出展:
  11. © ZOZO, Inc. arrival 16 Presentation Application Infrastructure Domain shared_kernel

    shipment Presentation Application Domain モジュラモノリス基盤について②: 変更しづらい部分 チーム単位で分割 /v1/shipment /v1/arrival - /receiving - /tanainput - さらに業務毎に分けている サブプロジェクトはチーム・レイヤー毎 サブプロジェクト間の依存関係は厳密に管理 Web APIのインターフェース レイヤー構成とその依存関係 もっと良い区切りが見つかれば、それに合わせて 逆コンウェイの法則的にチームを変更する手もあった
  12. © ZOZO, Inc. 17 モジュラモノリス基盤について②: 変更しづらい部分 最終的には全てひっくるめて Buildしてデプロイする arrival Presentation

    Application Infrastructure Domain shared_kernel shipment Presentation Application Domain サブプロジェクトはチーム・レイヤー毎 サブプロジェクト間の依存関係は厳密に管理 レイヤー構成とその依存関係 Web APIのインターフェース チーム単位で分割 /v1/shipment /v1/arrival - /receiving - /tanainput - さらに業務毎に分けている
  13. © ZOZO, Inc. Web APIのインターフェース チーム単位で分割 /v1/shipment /v1/arrival - /receiving

    - /tanainput - さらに業務毎に分けている 18 モジュラモノリス基盤について②: 変更しづらい部分 shipment arrival Presentation Application Infrastructure Domain shared_kernel Presentation Application Domain Infrastructure infrastructureも分離できれば デプロイ単位の分離も検討する
  14. © ZOZO, Inc. 20 Step1. API化: 本番環境を利用した等価比較 API化をリファクタリングと捉えて移行を進める APIリクエストして(=SQL実行して)レスポンスを 受け取り、(MVCの)モデルに反映するまで

    “外部の振る舞い” 「リファクタリングとは、ソフトウェアの外部の振る舞いを 保ったままで、内部の構造を改善していく作業を指します」 が保たれているかはテストで検証・担保する 出展: Martin Fowler著 「リファクタリング(第2 版) 既存のコードを安全に 改善する」(オーム社)
  15. © ZOZO, Inc. 21 モノリス Step1. API化: 本番環境を利用した等価比較 input 移行対象

    ユーザー操作 参照系(副作用なし)の場合 旧 モデル 操作
  16. © ZOZO, Inc. 22 モノリス Step1. API化: 本番環境を利用した等価比較 旧 input

    expected モデル操作の履歴 モデル 操作 新 input actual ダミーのモデル操作の履歴 ダミー モデル 操作 モジュラモノリス API 比較する 参照系(副作用なし)の場合 ユーザー操作
  17. © ZOZO, Inc. 23 モノリス Step1. API化: 本番環境を利用した等価比較 旧 ID

    IDと共に発行された 更新系SQL全部残す commit 新 ID rollback モジュラモノリス API 更新系(副作用あり)の場合 リクエスト毎に 適当なIDを発行 IDと共に発行された 更新系SQL全部残す 比較する
  18. © ZOZO, Inc. 24 API化 モジュール化 DB分割 マイクロ サービス化? Step.1

    Step.2 Step.3 Step.4 安定した境界を見つけるまで試行錯誤する
  19. © ZOZO, Inc. 25 Step2. モジュール化: ドメイン層を導入する arrival Presentation Domain

    shared_kernel Infrastructure ユースケース(トランザクションスクリプト) ベタ書きのロジックをドメイン層の 値オブジェクトに切り出していく ⇨ ドメインモデル形式に一歩踏み出す Application
  20. © ZOZO, Inc. module C 27 A A? B? C

    B module A module A module B A A? B? C B 参照のみ 更新含む このテーブルの値を更新ユースケースで利用する? 利用しない場合: 利用する場合: 分散トランザクション Step2. モジュール化: モジュールをまたがるトランザクションをときほぐす リードモデルの可能性が高く トランザクションが分離できる
  21. © ZOZO, Inc. 28 module A module B A C

    C module C B Event Event Read Model Updater AやBの更新トランザクションは それぞれ単体で完結できた Eventを導入してトランザクションを分離する 参照のみ 更新含む Step2. モジュール化: モジュールをまたがるトランザクションをときほぐす
  22. © ZOZO, Inc. 29 モジュール間の分散トランザクション module C module A module

    B A A? B? C B 同要件を満たしたい場合、複雑な実装なしで トランザクションは分離できない ⇨ 要件の見直しも視野に入れて対応していく Step2. モジュール化: モジュールをまたがるトランザクションをときほぐす
  23. © ZOZO, Inc. 31 事例①のまとめ • APIへの移行作業は良好で機械的な作業で安心して移行する流れが作れた • 移行して技術スタックが新しくなるだけでもメリットは大きい ◦

    リファクタリング(改善)する習慣が生まれたことで、設計も開発者の設計スキルも  向上、正のサイクルが生まれたので、絶対にこれを失ってはならない • モノリスの構造の理解は深まったが本当の意味でのモジュール化はハードルが高い ◦ 元々一つだったものをなんの犠牲もなしに疎結合にはできない、モノリスで実装した 過剰ともいえる機能は「機能的負債」と化している ◦ ユーザーに提供している機能の要件をリプレイスで下げることは容易ではないため、 ここからはユーザーとの調整・対話が必須 • モジュラモノリスへの移行が進めばデプロイ衝突など課題が出てきそう • モノリスに残ったビュー・バッチのリプレイスもこれから
  24. © ZOZO, Inc. 株式会社ZOZO 基幹システム本部 物流開発部 基幹リプレイスブロック 作田 航平 2022年に株式会社ZOZOに新卒入社。

    現在は、物流システムのリプレイスに従事。 趣味は、旅行、漫画、フットサル。 33
  25. © ZOZO, Inc. 38 Step.2 機能要件の定義 発送準備処理や発送終了処理は基幹システムに残したため双方向にデータのやり取りが必要 1. 発送準備が完了したデータを発送サービスに連携する 2.

    発送が完了したことを基幹システムに即時連携する また非機能要件として、発送業務をモジュール分割することにした ・・
  26. © ZOZO, Inc. 39 Step.3-1 モジュール設計 ドメインモデリングで集約と境界づけられたコンテキストを設計し、それに沿って モジュールに分割 • モジュールごとにマイクロサービス化も可能な構成にしているが、モジュール境界

    を跨いだ処理を実装する可能性があるため、個々のサービスには分割しないと判断 • ミクロな視点で見るとモジュラモノリス(?)な構成になっている
  27. © ZOZO, Inc. 44 Step.3-2 アーキテクチャ設計 2. 発送が完了したことを基幹システムに即時連携する CDCを実現するにあたり、Amazon DynamoDBやAWS

    Database Migration Serviceも検討 したが、AWSのオフィスアワーで相談させてもらい、MSKに決定した • モノリスからの脱却に向けた 物流システムリプレイスの概要紹介 コンシューマーは1秒間で最大200メッセージを処理できており要件を満たせている MSKの性能や仕様について理解が深まったため、使用技術を統一する目的で発送サービスへ のデータ連携もMSKにすることを検討中
  28. © ZOZO, Inc. 48 要件を満たすためにマイクロサービスにしたが、移行による痛みはある • サービスを跨いだ改修が大変 • アプリケーションの依存関係を考慮したリリースが必要 •

    インフラ基盤が複雑になったので学習コストが高い また、学習コストの高さがリプレイスを進める上でハードルになっている • 既存モノリスを開発しているメンバーの参入障壁を下げる努力が必要 ◦ 言語の習得だけでなく、アーキテクチャへの理解が必要 ◦ リプレイスについての勉強会を実施 マイクロサービス化による課題
  29. © ZOZO, Inc. 49 デメリットだけでなくメリットもきちんと享受できている • DBが分離されたので慢性的な速度低下に巻き込まれない • コードもDBも1から設計できたので読みやすくなった •

    影響範囲が明確になったので速度改善などが行いやすい • デプロイの単位が小さくなり、デプロイ頻度が高くなった マイクロサービス化によるメリット
  30. © ZOZO, Inc. 50 発送機能ではサービス境界を明確に決められたためマイクロサービス化に踏み切ったが、 本当にマイクロサービスにするのかは要件を整理した上で適切な議論が必要 発送サービスではモジュールを分けている • 機能ごとに責務を分離し、モジュール単位でチーム開発できるようにした •

    「デプロイ単位をチームごとにする」ことよりも「開発のしやすさ」を優先した 発送という大きな機能単位でサービスにしており、これ以上分割する予定はないが責務を 分離する上でモジュラモノリス的な構成になっている 事例②のまとめ マイクロサービスは選択肢を買い与える 出典:Sam Newman著「モノリスからマイクロサービスへ」(O'Reilly Japan)
  31. © ZOZO, Inc. 52 全体まとめ① モジュラモノリス • 境界について深く考えずに一歩が踏み出せる、モジュラモノリスに移行したことで改善 サイクルが生まれ、それだけでも十分メリットを享受できた •

    モジュール性を高めていくにはユーザーと対話して要件から見直すことも必要 マイクロサービス • 社内向けシステムであることを活かし現場の協力を得られれば大胆にマイクロサービス 移行することも可能で、DBを新規設計できるのはメリットが大きい • トランザクションを分離できる確信が得られれば選択肢の一つ どちらも一長一短あるので使い分けていく ただし発送のようにマイクロサービス化によって大きなリターンが得られる機能は多くない ので、モノリスに残る機能もまずは入荷のようにモジュラモノリスに移行する