精読「モノリスからマイクロサービスへ (1)」
モノリスからマイクロサービスへ ―モノリスを進化させる実践移行ガイド
従来のモノリシックアーキテクチャを現代のビジネスニーズに適応させるための実践的な移行手法を網羅した一冊です。本書では、マイクロサービスの基本的な概念や利点だけでなく、移行プロジェクトで直面する課題とその解決方法を具体例を交えながら解説しています。
また、技術的なアプローチだけでなく、組織的・文化的な側面にも焦点を当て、チーム全体でのスムーズな移行を支援します。実務で活用できる戦略やツール、ステップバイステップのガイドを提供しているため、モノリスに課題を感じている開発者やアーキテクト、プロジェクトリーダーに最適です。
これからのシステム開発に必要なスキルと知識を身につけ、進化するシステムの未来を切り拓きたい方にぜひおすすめしたい一冊です。
関連記事
必要十分なマイクロサービス
マイクロサービスアーキテクチャについて深く理解することは、その利点を最大限に引き出すための第一歩。本章では、一般的な誤解や見落とされがちな要素に触れながら、アーキテクチャの基本的な概念を整理する。
さらに、モノリシックアーキテクチャとの比較を通じて、マイクロサービスがどのように発展してきたかを振り返り、その利点と直面し得る課題についても詳しく解説する。
マイクロサービスとは
1.1 マイクロサービスとは
マイクロサービスは、ビジネスドメインを基に設計され、独立してデプロイ可能なサービス群のこと。これらはネットワーク越しに通信し合い、全体として1つのシステムを形成する。
主な特徴
- 独立デプロイ可能性: 変更したサービスのみを他に影響なくリリースできる。
- ビジネスドメインに基づくモデル化: 機能をビジネスロジックに基づいて分割し、技術的な境界を超えて変更する手間を削減。
- データの独立所有: 各サービスは自身のデータを持ち、他サービスと共有しない。
マイクロサービスと従来アーキテクチャの比較
伝統的な3層構造(UI、ビジネスロジック、データ層)では、変更が複数層やチームにまたがりがち。対して、マイクロサービスはドメインごとに独立した構成で、変更範囲を局所化できる。
メリット
- 変更の影響を限定できるため迅速なデプロイが可能。
- ビジネス機能単位でのチーム編成が可能になり、効率的な運用が実現。
モノリス
モノリスの定義
- モノリスとは、システム内のすべての機能を一緒にデプロイする必要がある構造を指す。
- 主にデプロイの単位で分類される。
モノリスの種類
-
単一プロセスのモノリス:
- 全てのコードが単一プロセスにパッケージ化。
- データベースと連携することで単純な分散システムに見える場合もある。
- 一般的に最も議論される形態で、多くの課題が集中している。
-
モジュラーモノリス:
- 単一プロセス内で複数のモジュールに分割されたシステム。
- 境界が明確であれば高度な並列作業が可能。
- デプロイ時にモジュールが結合される必要がある点で課題も抱える。
-
分散モノリス:
- 複数のサービスで構成されるが、一体としてデプロイされる必要がある。
- 単一プロセスモノリスと分散システムの欠点を併せ持つ。
-
サードパーティ製ブラックボックスシステム:
- 外部の既成ソフトウェアを含む。
- 自身でコードを変更できないが、分解技術を適用できる場合もある。
モノリスの課題
- 結合が強く、変更の波及や所有権の曖昧さにより開発効率が低下する(デリバリー衝突)。
- 特に単一プロセスのモノリスでは、複数人が同じコードを変更する際の競合が頻発する。
モノリスの利点
- デプロイがシンプル。
- 分散システム特有の課題(監視やトラブルシューティングの複雑化)を回避。
- コード再利用が容易。
- アーキテクチャ選択肢としては今も有効で、全てのケースで悪ではない。
モノリスを避けるべきものと考えるのではなく、マイクロサービスとのトレードオフを理解し、適切な状況で使い分けるべき。
結合と凝集
結合と凝集は、システムのモジュール間での関係性を説明する概念。これらの関係はマイクロサービスの境界を定義する際に重要で、特に分散システムの構築においては重要な要素。
結合と凝集の関係
- 結合(Coupling):異なるモジュール間での依存関係を指し、一方の変更がもう一方にどれほど影響を与えるかを示す。結合が強いと、変更のコストが高く、サービス間の相互作用が増え、変更の自由度が制限される。
- 凝集(Cohesion):モジュール内部での一貫性を指し、モジュール内のコードや機能がどれほど関連しているかを示す。凝集度が高いほど、モジュール内の変更が一貫しており、変更が局所化される。
コンスタンティンの法則
- 「構造は、凝集度が高く、結合度が低い場合に安定する」という考え方は、マイクロサービスアーキテクチャにも当てはまる。高い凝集度と低い結合度は、モジュールの変更を容易にし、システム全体を安定させるために重要。
結合と凝集の影響
- 分散システムでは、サービス間の結合度が高くなると、サービス間での変更が他のサービスにも影響を与える可能性が高くなる。これにより、変更のコストが大きくなり、サービスの独立したデプロイや更新が難しくなる。
- モノリスの場合、凝集度は高くても結合度が強すぎると、システム全体を再デプロイする必要があり、変更が難しくなる。
結合の分類と情報隠蔽
- 情報隠蔽(Information Hiding):モジュール内で頻繁に変更されるコードを外部から隠すことで、システム全体の安定性を保つ方法。モジュールの詳細な実装を隠蔽することで、外部の変更に対する影響を最小限に抑えられる。
- 実装結合:モジュール間で実装詳細に依存する結合で、最も避けるべき結合。例えば、データベースを共有する場合、スキーマ変更が他のサービスに影響を与える可能性があり、変更の自由度が制限される。
マイクロサービスにおける結合と凝集の実践的アプローチ
- 安定したサービス契約を保ちながら、サービス間での結合を最小化し、変更をサービス内に局所化することが推奨される。
- API経由でのデータアクセスや、サービスインターフェイスの設計は、内部実装を隠蔽するための効果的な方法。
このように、結合と凝集は、マイクロサービスの設計において重要な役割を果たし、システムの変更や維持管理のしやすさに大きな影響を与える。
必要十分なドメイン駆動設計
ドメイン駆動設計(DDD)の概念をマイクロサービスアーキテクチャに適用する方法について。特に「集約」と「境界づけられたコンテキスト」の概念が中心となっている。
-
集約: 集約は実際のドメイン概念(注文や請求書など)を表現する単位であり、ライフサイクルを持つ自己完結型のユニットとして設計される。集約内の状態遷移は、外部からの不正な要求を防ぐように実装するのが理想。また、集約は他の集約と関連を持つことがあり、複数の集約を一つのサービス内で処理することが考えられる。
-
境界づけられたコンテキスト: 境界づけられたコンテキストは、集約よりも大きな単位で、明確な責任を持つ組織境界を表す。境界づけられたコンテキスト内で使用される概念(例: 倉庫で使用されるフォークリフトの種類など)は、他のコンテキストとは隠蔽されるべき。実装上、境界づけられたコンテキストには複数の集約が含まれ、それらが内外で異なる公開・隠蔽の範囲を持つことがある。
-
マイクロサービスへのマッピング: 集約と境界づけられたコンテキストは、それぞれマイクロサービスの境界として適切に機能する。マイクロサービス化を進める初期段階では、サービスをできるだけ少なくし、その後、境界づけられたコンテキストを基にサービスを分割することが一般的。分割後も、外部からの変更は隠蔽できるように、APIの粒度などを工夫する。
このように、DDDの概念を活用して、マイクロサービスの設計をより効果的に行うことができる。特に、集約と境界づけられたコンテキストをどのように定義するかが、マイクロサービスの成功に重要な役割を果たす。
この章のまとめ
マイクロサービスがビジネスドメインに基づき独立したサービスとしてデプロイされ、ネットワークを通じて相互に通信する。情報隠蔽とドメイン駆動設計を活用し、独立した安定したサービス境界を作り、結合を減らす。
移行を計画する
モノリス分解の技術的な詳細に入る前に、次の課題を考える必要がある。移行の開始地点、変化の管理方法、他者の巻き込み方、そして「マイクロサービスを使うべきか」という基本的な問い。
目的を理解する
目的を理解する
-
マイクロサービスは手段であり目的ではない。
- 移行は、現行システムでは達成できない目標を実現するための合理的判断に基づくべき。
-
目的が不明確だと失敗につながる。
- 理由を理解せずに移行を始めると、移行作業が優先され本来の目的が見失われる可能性がある。
- 他社の成功事例を模倣するだけでは本質を理解できない(カーゴカルト的アプローチの危険性)。
ROIやコスト効果を具体的に測るのは難しいが、クリティカルシンキングと実験的アプローチが必要。
3つの重要な質問
-
達成したいことは何か?
- システムがエンドユーザーにどんなメリットをもたらすかを明確にする。
-
他の代替案はないのか?
- マイクロサービス以外の方法で利点が得られるかを検討すべき。簡単な解決策も選択肢。
-
移行の成功をどう判断するか?
- 成功の指標を定義し、進捗を評価する方法を明確にする。
マイクロサービス化を進める前に、明確な目的とその達成手段を冷静に検討する必要がある。
マイクロサービスを選択する理由
チームの自律性を高める
マイクロサービスは、各チームが独立して開発・運用を行える環境を作り、自律性を向上させる。これにより、迅速な意思決定と効率的な作業が可能になる。他の方法として、モジュラーモノリスを採用し、コードの所有権や責任を分割する方法も有効。
市場投入までの時間を短縮する
個別のマイクロサービスを独立してデプロイできるため、機能を迅速にリリース可能。他には、プロセスのボトルネックを特定し改善することで、アーキテクチャ変更なしにデリバリー速度を向上させられる。
費用対効果の高いスケーリング
マイクロサービスは必要な部分だけをスケールできるため、効率的なリソース活用が可能。他には、既存モノリスの垂直スケーリングや水平スケーリングを試す選択肢もある。
堅牢性の向上
障害が特定のサービスに限定されるため、全体への影響を最小限に抑えられる。他の方法として、モノリス内で障害を分離する設計を工夫することも可能。
マイクロサービスが悪いアイデアのとき
不明瞭なドメイン
サービス境界を誤ると、変更や結合のコストが高まり、モノリシックシステムより非効率になることがあります。たとえば、SnapCI開発チームは初期にサービスを分割しすぎて問題が発生し、最終的に一度モノリシックに統合しました。ドメインを深く理解する前に分解を進めると、コストが高くつく場合があります。まずはドメイン理解を優先しましょう。
スタートアップ
スタートアップの段階では、製品や市場フィットの探索が優先されます。この段階でマイクロサービスを採用すると、頻繁な方向転換に伴うコストが問題になります。成熟したプロダクトやスケールが求められる段階で初めて、マイクロサービスのメリットが発揮されることが多いです。
顧客環境で管理されるソフトウェア
顧客が直接運用するソフトウェアの場合、マイクロサービスは運用の複雑さを顧客に押し付ける結果になることがあります。顧客がその運用に必要なスキルや環境を持っているとは限らないため、モノリシックシステムの方が適していることが多いです。
明確な目的がないとき
何を達成したいのか明確でない場合、マイクロサービスの採用は失敗する可能性があります。移行の目的や目標を明確にせずに進めると、無駄なコストを生むことになりかねません。「流行っているから」という理由だけで採用するのは避けましょう。
トレードオフ
プロジェクトが複雑化する原因の一つは、目的を一度に達成しようとする姿勢にある。マイクロサービス導入においては、主要目的を中心に据え、副次的な目的を適切に後回しにすることが成功の鍵。スライダーを活用した視覚的な優先順位付けは、目標達成を効果的に支援するツールとなる。
みんなを連れて行く
マイクロサービス導入において関係者との共通理解を築くことが重要。異なる意見がある場合は、目標を再確認し、それに基づいてアイデアを共有することで変革への協力を得やすくなるとしている。また、組織変革を支援するモデルを活用することで、アイデアの実現を助けることができる。
組織を変革する
John Kotterの組織変革モデルは、8段階のプロセスで変革を実現する方法を示したもので、広く用いられている。このモデルは大規模な組織変革に適しているが、小規模な変更にも有用。特に初期ステップでは、マイクロサービスの導入などの変革でも役立つとされている。各手順を踏むことで、変革がスムーズに進むとされている。
組織変革を成功に導くステップとプロセス|段階的アプローチのやり方・注意点・対策を解説!より
段階的に移行していくことの重要性
マイクロサービスへの移行は段階的に行うことが推奨される。ビッグバン方式で一度に全てを移行しようとすると、何がうまくいっているのか把握するのが難しく、失敗の影響も大きくなる。段階的に進めることで、各ステップから学び、失敗のリスクを最小限に抑えることができる。特に、本番環境で実際に利用されることで初めて気づく問題が多いため、移行の過程で得られる教訓が非常に重要。少しずつ分解して学んでいくアプローチが効果的。
変更のコスト
変更のコストとその管理方法について、重要なのは、決定の可逆性と不可逆性を理解し、最適な判断を行うこと。可逆的な決定(後で軌道修正が可能なもの)と不可逆的な決定(変更が困難なもの)の違いを把握し、可逆的な決定を優先することで、失敗の影響を軽減できます。
特に、コードの移動や変更は比較的低コストで行えるが、データベースの分割やサービス間の統合解除は高コストでリスクを伴う。したがって、最初は影響が小さく、修正が容易な領域で変更を試み、そこから学んでいくことが推奨される。
どこから始めればよいか?
モノリシックシステムをマイクロサービスに分解する際に、論理的な分解が重要であり、そのために「ドメイン駆動設計(DDD)」を活用するべき。DDDを使うことで、ビジネスの領域に基づいて意味のあるサービスを構築できる。
ドメイン駆動設計
ドメイン駆動設計(DDD)を活用し、モノリシックシステムをマイクロサービスに分解する方法については以下の通り。
- ドメインモデル作成: モノリスの分解にはドメインモデルが役立ち、どの機能を分解するかを判断できる。
- 範囲の設定: 初めにシステムを大まかに分解し、後から詳細化。
- イベントストーミング: ドメインイベントを定義し、共同でモデルを作成する手法。
- 優先順位付け: 分解のしやすさをドメインモデルで評価し、最適な分解順序を決定。
この方法で、マイクロサービス化を進める。
組み合わせモデル
サービス分解の優先順位を付けるために、価値と難易度を基準にした「組み合わせモデル」を紹介している。
- 優先順位付け: 分解の価値(x軸)と難易度(y軸)を軸にして、候補となるサービスを配置。
- 象限モデル: 右上の象限が理想的で、まずここから抽出候補を選ぶ。
-
柔軟な調整: 進行に伴い、難易度や価値が変化する可能性があり、その都度優先順位を見直すことが重要。
この方法で、最適な分解ポイントを見つけることができる。
チームを再編成する
マイクロサービスへの移行を成功させるために、アーキテクチャの変更とともに組織構造の見直しが重要。
組織構造の変革
歴史的にIT組織は専門ごとに分かれており、ソフトウェア開発ではチーム間でのバトンパスが必要だった。しかし、現在では、開発者、テスター、運用チームが統合され、デリバリーチームが全責任を持つ方向にシフトしている。
組織の変革には慎重なアプローチが必要
他社の組織モデルをそのまま真似るのは危険。Spotifyモデルなどの成功事例も、その企業文化や文脈に適応しているだけで、他の組織にそのまま適用するのは失敗の元。自社の文脈に合わせて柔軟に考えることが重要。
変化を起こす
変革を始めるには、ソフトウェアデリバリーに関わる全ての活動と責任を明確化し、それを既存の組織構造にマッピングする。全員で現状を理解し、どのチームがどこまで責任を持っているかを把握することで、変化をスムーズに進められる。
うまくいっているかどうかを分かるには?
マイクロサービスへの移行がうまくいっているかをどう判断するかについて。進捗を評価するためには定量的な指標とともに、現場の定性的なフィードバックを考慮することが重要。
定期的なチェックポイント
定期的に振り返り、進捗を確認することが必要。小規模なチームでは非公式なものでも良いが、大規模なプログラムでは定期的なセッションを設けることが求められる。
定量的な測定
進捗を追跡するために使用する指標は目標によって異なり、サイクルタイムやデプロイ数などが例として挙げられる。ただし、メトリクスには誤用のリスクがあるため、注意が必要。
定性的な測定
ソフトウェア開発は感情的な側面も大きいため、チームの感情やフィードバックも重要な指標となる。人々がプロセスを楽しんでいるか、圧倒されていないかなどを確認することが必要。
サンクコストの錯誤を回避する
進行中のプロジェクトに過剰に投資しすぎないようにし、問題があれば早期に軌道修正することが重要。サンクコストにとらわれず、柔軟に方向転換を行うべき。
新しいやり方への選択肢を開いておく
変更を取りやめたり、試す新しい方法にオープンであることが大切。絶え間ない改善の文化を受け入れ、変化を適切に取り入れていく必要がある。
この章のまとめ
マイクロサービスアーキテクチャへの移行に関する重要なポイントは以下の通り。
-
マイクロサービス採用の理由と意思決定の影響:マイクロサービスを選択する理由を明確にし、その決定がチームの時間の使い方や優先順位にどう影響するかを考えることが重要。
-
重要な質問事項:マイクロサービスが適切かどうかを判断するために、以下の質問に答える必要があるとされている
- 何を達成したいのか?
- マイクロサービス以外に代替案はなかったか?
- 移行がうまくいっているかどうかをどう判断するか?
-
段階的なアプローチの重要性:マイクロサービスへの移行は段階的に行うべき。最初から完璧を目指すのではなく、小さな間違いを許容し、間違いを最小限に抑え、学びながら進むことが大切。
-
顧客を意識した移行:既存のシステムを無視して大規模なリライトを行う余裕はなく、新しいマイクロサービスを少しずつ作成し、実際の顧客が使っている環境でデプロイしていくことが求められている。これにより、実際に学びながら進め、早期に利益を得ることができる。
-
移行作業の進行:新しいマイクロサービスを作成し、縮小しつつあるモノリスと統合し、実際に本番環境で運用するプロセスから多くを学び、徐々に移行を進めることが求められている。
Discussion