マイクロサービスの最大の課題の 1 つは、個々のサービスの境界の定義です。 一般的なルールは、サービスは 1 つだけの処理を行う必要がありますが、そのルールを実践するには慎重に考える必要があります。 正しい設計を生み出す機械的なプロセスはありません。 ビジネス ドメイン、要件、アーキテクチャの特性 ( 非機能要件とも呼ばれます) と目標について深く考える必要があります。 そうしないと、サービス間の依存関係、緊密な結合、または適切に設計されていないインターフェイスを含む非構造化設計が作成されるリスクがあります。 この記事では、マイクロサービスを設計するためのドメイン駆動のアプローチについて説明します。 サービス境界の評価は、ワークロードを進化させるための継続的な取り組みです。 場合によっては、評価によって、変更に対応するためにより多くのアプリケーション開発が必要な再定義された境界が生じることがあります。
この記事では、継続的な例としてドローン配送サービスを使用します。 シナリオと対応する参照実装の詳細については、「 マイクロサービス アーキテクチャの設計」を参照してください。
はじめに
データ アクセスやメッセージングなどの水平レイヤーではなく、ビジネス機能に関するマイクロサービスを設計します。 マイクロサービスが疎結合であり、機能的凝集が高いことを確認します。 他のサービスを同時に更新せずに 1 つのサービスを変更できる場合、マイクロサービスは 疎結合 されます。 マイクロサービスに、ユーザー アカウントの管理や配信履歴の追跡など、明確に定義された単一の目的がある場合、マイクロサービスは まとまり があります。 サービスはドメインの知識をカプセル化し、クライアントからその知識を抽象化する必要があります。 たとえば、クライアントは、スケジューリング アルゴリズムやドローンフリート管理に関する知識がなくても、ドローンをスケジュールできます。
各マイクロサービスのアーキテクチャ特性は、システム全体に対して定義するのではなく、そのドメインの懸念事項と一致するように定義する必要があります。 たとえば、顧客向けのマイクロサービスには、パフォーマンス、可用性、フォールト トレランス、セキュリティ、テスト可能性、機敏性が必要な場合があります。 バックエンド マイクロサービスでは、フォールト トレランスとセキュリティのみが必要な場合があります。 マイクロサービスが同期的に通信する場合、多くの場合、ランタイムの依存関係では、同じアーキテクチャ特性を共有する必要があります。
ドメイン駆動型設計 (DDD) は、適切に構造化されたマイクロサービスの設計をサポートするフレームワークを提供します。 DDD には 戦略的 フェーズと 戦術的 フェーズがあります。 戦略的 DDD では、大規模なシステム構造を定義します。 戦略的 DDD は、アーキテクチャがビジネス機能に集中し続けることを保証します。 戦術的 DDD には、ドメイン モデルの作成に使用できる設計パターンが用意されています。 これらのパターンには、エンティティ、集約、およびドメイン サービスがあります。 これらの戦術的パターンは、疎結合でまとまりのあるマイクロサービスを設計するのに役立ちます。
ユビキタス言語の概念は、DDD の中心です。 これは、開発者とドメインの専門家が境界付けられた各コンテキスト内で一緒に作成する共有ボキャブラリです。 Teams は、会話、ドキュメント、およびコードでこの言語を一貫して使用します。 同じ用語がこれらすべての領域で同じことを意味する場合、チームは誤解を減らし、ビジネスの意図を正確に反映するドメイン モデルを生成します。 境界付けられた各コンテキストは、独自のユビキタス言語を持つことができます。つまり、同じ単語 ( アカウントなど) が異なるコンテキストで異なる意味を持ちます。
この記事と関連する 戦術的 DDD に関する記事では、次の手順を示し、ドローン配送アプリケーションに適用します。
ビジネス ドメインを分析して、アプリケーションの機能要件を理解します。 この手順の出力は、ドメインの非公式な説明であり、より正式なドメイン モデルのセットに絞り込むことができます。
ドメインの 境界付けられたコンテキスト を定義します。 境界付けられた各コンテキストには、大規模なアプリケーションの特定のサブドメインを表すドメイン モデルが含まれています。
境界付けられたコンテキスト内で戦術的な DDD パターンを適用して、エンティティ、集計、およびドメイン サービスを定義します。
前の手順の結果を使って、アプリケーションのマイクロサービスを識別します。
この記事では、主に戦略的 DDD に関する最初の 2 つの手順について説明します。 記事「戦術的 DDD」では、手順 3 について説明します。 「 マイクロサービスの境界を特定する 」の記事では、手順 4 について説明します。 DDD は反復的で継続的なプロセスであるため、サービスの境界は固定されたままになりません。 アプリケーションが進化するにつれて、1 つのサービスを複数の小さなサービスに分割する場合があります。
注意
この記事では、ドメインの完全かつ包括的な分析については説明しません。 この例は意図的に簡潔で、主なアイデアに焦点を当てています。 DDD について詳しくは、最初にこの用語を導入した書籍である Eric Evans の Domain-Driven デザインをご覧ください。 もう一つの良い参考書としては、ヴラド・コンノノフによる「Learning Domain-Driven Design」があります。この本は、主題に対する実用的で現代的なアプローチを提供します。
シナリオ:ドローン配送
Fabrikam, Inc. は、ドローン配送サービスを開始します。 同社は、ドローン機団を管理しています。 企業はサービスに登録し、ユーザーは配送のために商品を受け取るためにドローンを要求します。 顧客が集荷をスケジュールすると、バックエンド システムによってドローンが割り当てられ、推定配送時間がユーザーに通知されます。 配送が進行する間、顧客はドローンの場所を追跡し、継続的に更新された推定到着時間 (ETA) を使用します。
このシナリオには複雑なドメインが含まれます。 ビジネス上の主な懸念事項には、ドローンのスケジュール設定、パッケージの追跡、ユーザー アカウントの管理、履歴データの格納と分析の方法が含まれます。 Fabrikam はまた、市場に迅速に到達し、新しい機能を追加するために迅速に反復することを目的としています。 アプリケーションはクラウド 規模で動作し、高いサービス レベル目標 (SLO) を満たす必要があります。 また、Fabrikam では、システムのさまざまな部分に、データ ストレージとクエリ操作に関する要件が異なることも想定されています。 これらの考慮事項により、Fabrikam はドローン配送アプリケーション用のマイクロサービス アーキテクチャを採用します。
ドメインを分析する
DDD アプローチは、各サービスが機能的なビジネス要件に自然に合うようにマイクロサービスを設計するのに役立ちます。 また、組織の境界やテクノロジーの選択によって設計が左右されないようにするのにも役立ちます。
ヒント
Conway の法律では 、システムはそれらを構築する組織の通信構造を反映する傾向があることを観察しています。 そのミラーリングがパッシブに行われると、ビジネス ドメインではなく組織図を反映するアーキテクチャにつながる可能性があります。 ドメイン分析によってサービス境界を定義し、意図的にチームの所有権をそれらの境界に合わせることにより、DDD を活用できます。 このプロアクティブなアプローチにより、チーム構造がアーキテクチャと競合するのではなく、そのアーキテクチャをサポートすることが保証されます。
1 つのチームが複数の関連のない境界付きコンテキストを所有する必要がある場合、または 1 つの境界付きコンテキストで多くのチーム間の調整が必要な場合は、境界またはチーム構造を見直します。
コードを記述する前に、ビルドするシステムの概要を理解しておく必要があります。 DDD はビジネス ドメインをモデル化し、 ドメイン モデルを作成します。 ドメイン モデルはビジネス用ドメインの抽象化モデルです。 ドメインの知識を蒸留して整理し、開発者とドメインの専門家のための共有言語を確立します。
まず、すべてのビジネス機能とそれらの間の接続をマッピングします。 この作業には、ドメインの専門家、ソフトウェア アーキテクト、およびその他の利害関係者が関与する必要があります。 特定の正式な方法に従う必要はありません。 たとえば、図をスケッチしたり、ホワイトボードを使用したりすることができます。 構造化されたアプローチの 1 つに、 イベント ストームが含まれます。 イベント ストームを使用する場合でも、あまり正式でないアプローチを使用する場合でも、目標は、テクノロジを選択する前にドメインの共有理解を構築することです。
図を入力すると、個別のサブドメインの識別が開始される場合があります。 次のパターンを探します。
密接に関連する関数
ビジネスの鍵となる関数と、サポート サービスを提供する関数
関数間の依存関係グラフ
この初期フェーズでは、テクノロジや実装の詳細に焦点を当てないでください。 ただし、顧客関係管理、支払い処理、課金システムなど、アプリケーションを外部システムと統合する必要がある場所を特定する必要があります。
例:ドローン配送アプリケーション
最初のドメイン分析の後、Fabrikam チームはドローン配送ドメインを示す大まかなスケッチを作成します。
出荷は ビジネスの中核であるため、図の中央に表示されます。 この機能をサポートするために、図の他のすべてのものが存在します。
ドローンの管理もビジネスの中核です。 ドローン管理に密接に関連する機能には、ドローンの修理や予測分析を使用して、ドローンのサービスとメンテナンスが必要なタイミングを予測することが含まれます。
ETA 分析は集配の時間を見積もります。
サードパーティの輸送により 、パッケージをドローンで完全に出荷できない場合に、アプリケーションで代替輸送方法をスケジュールできます。
ドローンの共有は、コア ビジネスを拡張するものです。 会社は、特定の時間に過剰なドローン容量を持っている可能性があり、アイドル状態のドローンを貸し出すことができます。 初期リリースには、この機能は含まれていません。
ビデオ監視は、企業が後から展開する可能性のあるもう 1 つの分野です。
ユーザー アカウント、 請求、 コール センター は、コア ビジネスをサポートするサブドメインです。
DDD はサブドメインを 3 つのカテゴリに分類します。この分類は、設計作業を最も多く投資する場所に優先順位を付けるのに役立ちます。
コア サブドメインは競争上の 優位性を提供します。 Fabrikam の出荷とドローン管理は、ビジネスを定義するため、Fabrikam のコア サブドメインを形成します。 これらのサブドメインには、詳細なモデリングと多額のチーム投資が必要です。
サブドメインをサポートすると 、ビジネスは稼働し続けますが、競合他社とは区別されません。 請求はこのカテゴリに分類されます。 カスタム開発が必要ですが、競争上の優位性のソースとしては機能しません。
一般的なサブドメインは、 業界が既に解決した問題を表します。 ユーザー アカウントとコール センターは、Fabrikam がカスタム構築システムではなく、既存の事前構築済みソリューションまたは標準ソリューションを使用して対処できる汎用サブドメインを形成します。
このプロセスのこの時点で、Fabrikam は実装やテクノロジに関する決定を行っていません。 一部のサブシステムには、外部ソフトウェア システムまたは Microsoft 以外のサービスが含まれる場合があります。 ただし、アプリケーションはこれらのシステムとサービスとやり取りする必要があるため、Fabrikam はドメイン モデルにそれらを含めます。
注意
アプリケーションが外部システムに依存している場合、外部システムのデータ スキーマまたは API がアプリケーションにリークする可能性があります。 この漏れにより、アーキテクチャの設計が損なわれる可能性があります。 最新のベスト プラクティスに従っていなくても、複雑なデータ スキーマや古い API を使用する可能性があるレガシ システムでは特に一般的です。 このような場合は、外部システムとアプリケーションの間に明確に定義された境界を確立します。 この境界を強制するには、ストラングラー フィグ パターンや破損対策レイヤー パターンの使用を検討してください。
境界付けられたコンテキストを定義する
ドメイン モデルには、ユーザー、ドローン、パッケージ、その他のエンティティなどの実際のエンティティの表現が含まれています。 ただし、これは、システムの各部分が同じエンティティに同じ表現を使用する必要があることを意味するわけではありません。
たとえば、ドローンの修理と予測分析を処理するサブシステムでは、メンテナンス履歴、走行距離、年齢、モデル番号、パフォーマンス特性など、ドローンの多くの物理的特性を表す必要があります。 しかし、配達をスケジュールする時になると、それらの詳細は無関係になります。 スケジューリング サブシステムは、ドローンが使用可能かどうかと、集荷と配送のための ETA のみを認識する必要があります。
両方のサブシステムに 1 つのモデルを作成すると、不要な複雑さが生まれます。 また、このモデルは、個別のサブシステムで作業する複数のチームを変更する必要があるため、時間の経過と同時に進化が困難になります。 その結果、2 つの異なるコンテキストで、同じ現実世界のエンティティ (この場合はドローン) を表す個別のモデルを設計することをお勧めします。 各モデルには、そのコンテキスト内で関連する特徴と属性のみが含まれます。
ここでは、境界付きコンテキストの DDD 概念が適用されます。 境界付きコンテキストは、特定のドメイン モデルが適用されるドメイン内の境界を定義します。 Fabrikam では、異なる関数が同じドメイン モデルを共有しているかどうかに基づいて機能をグループ化できます。
境界付きコンテキストは、必ずしも互いに分離されるとは限りません。 前の図では、境界付けられたコンテキストを接続する実線は、2 つの境界付けられたコンテキストが対話する場所を表しています。 たとえば、配送プロセスは、顧客情報を取得するためのユーザーアカウント管理と、フリートからドローンを適切にスケジュールするドローン管理システムに支えられています。
Fabrikam はこれらの相互作用を識別し、境界 付けられたコンテキスト 間の関係を文書化するコンテキスト マップを作成します。 コンテキスト マップでは、統合ポイントが強調表示され、チームが責任を明確にするのに役立ちます。 Evans とその後の DDD 実践者は、いくつかの関係パターンについて説明します。
顧客サプライヤー: 1 つのコンテキスト (アップストリーム) は、別のコンテキスト (ダウンストリーム) が依存するデータまたはサービスを提供します。 チームは、それらの間の契約を交渉します。
オープン ホスト サービス と 公開言語: アップストリーム コンテキストは、ダウンストリーム コンテキストが使用する共有形式 (発行済み言語) で記述された明確に定義された API (Open Host Service) を公開します。
破損防止レイヤー: ダウンストリーム チームは、上流モデルの変更からモデルを保護するための 翻訳レイヤー を構築します。
別の方法: 2 つのコンテキストには統合がありません。 各コンテキストは個別に進化します。
マイクロサービス アーキテクチャでは、マイクロサービスが明確に定義された API を介して通信するため、Open Host Service と発行言語が特に関連します。 マイクロサービスの設計 API に関する記事では、OpenAPI 仕様を使用して、JSON または YAML 形式で表される REST API の言語に依存しないインターフェイスの説明を定義する方法について説明します。
この旅の残りの部分では、出荷の境界付けコンテキストに注目します。
次のステップ
ドメイン分析を完了したら、戦術的な DDD を適用して、ドメイン モデルをより正確に定義します。