マイクロサービス境界の識別Identifying microservice boundaries

マイクロサービスの適切なサイズとは何でしょうか。What is the right size for a microservice? "大きすぎず小さすぎず" といったことをよく耳にします。確かにそのとおりですが、実際にはほとんど役に立ちません。You often hear something to the effect of, "not too big and not too small" — and while that's certainly correct, it's not very helpful in practice. しかし、慎重に設計されたドメイン モデルから始めると、マイクロサービスについてずっと簡単に類推できます。But if you start from a carefully designed domain model, it's much easier to reason about microservices.

境界付けられたコンテキストの図

この記事では、継続的な例としてドローン配送サービスを使用します。This article uses a drone delivery service as a running example. シナリオおよび対応する参照実装の詳細については、こちらを参照してください。You can read more about the scenario and the corresponding reference implementation here.

ドメイン モデルからマイクロサービスにFrom domain model to microservices

前の記事では、ドローン配送アプリケーションの境界付けられたコンテキストのセットを定義しました。In the previous article, we defined a set of bounded contexts for a Drone Delivery application. それから、これらの境界付けられたコンテキストの 1 つである "出荷" 境界付けられたコンテキストを詳しく調べて、その境界付けられたコンテキストのエンティティ、集計、ドメイン サービスのセットを明らかにしました。Then we looked more closely at one of these bounded contexts, the Shipping bounded context, and identified a set of entities, aggregates, and domain services for that bounded context.

その結果、ドメイン モデルからアプリケーション設計に移行する準備ができています。Now we're ready to go from domain model to application design. ドメイン モデルからマイクロサービスを導き出すために使うことができるアプローチを次に示します。Here's an approach that you can use to derive microservices from the domain model.

  1. 境界付けられたコンテキストから始めます。Start with a bounded context. 一般に、マイクロサービスの機能は、複数の境界付けられたコンテキストにまたがっていてはなりません。In general, the functionality in a microservice should not span more than one bounded context. 定義上、境界付けられたコンテキストは特定のドメイン モデルの境界をマークします。By definition, a bounded context marks the boundary of a particular domain model. 1 つのマイクロサービスに複数の異なるドメイン モデルが含まれることがわかった場合は、前に戻ってドメイン分析を修正する必要があることを示しています。If you find that a microservice mixes different domain models together, that's a sign that you may need to go back and refine your domain analysis.

  2. 次に、ドメイン モデルの集計を確認します。Next, look at the aggregates in your domain model. 集計はマイクロサービスの適切な候補になることがよくあります。Aggregates are often good candidates for microservices. 適切に設計された集計は、次のような適切に設計されたマイクロサービスの特徴を多く備えています。A well-designed aggregate exhibits many of the characteristics of a well-designed microservice, such as:

    • 集計は、データ アクセスやメッセージングなどの技術的な問題ではなく、ビジネス要件から派生します。An aggregate is derived from business requirements, rather than technical concerns such as data access or messaging.
    • 集計には、機能の高い凝集度が必要です。An aggregate should have high functional cohesion.
    • 集計は永続性の境界です。An aggregate is a boundary of persistence.
    • 集計同士は疎に結合されている必要があります。Aggregates should be loosely coupled.
  3. ドメイン サービスもマイクロサービスに適した候補です。Domain services are also good candidates for microservices. ドメイン サービスは、複数の集計に対するステートレスな操作です。Domain services are stateless operations across multiple aggregates. 典型的な例は、複数のマイクロサービスを含むワークフローです。A typical example is a workflow that involves several microservices. ドローン配送アプリケーションで、その例を見ることができます。We'll see an example of this in the Drone Delivery application.

  4. 最後に、機能以外の要件を検討します。Finally, consider non-functional requirements. チームの規模、データの型、テクノロジ、スケーラビリティの要件、可用性の要件、セキュリティの要件などの要因を確認します。Look at factors such as team size, data types, technologies, scalability requirements, availability requirements, and security requirements. これらの要因により、1 つのマイクロサービスを複数の小さいサービスにさらに分割したり、その逆に、複数のマイクロサービスを 1 つに結合したりすることになる場合があります。These factors may lead you to further decompose a microservice into two or more smaller services, or do the opposite and combine several microservices into one.

アプリケーション内のマイクロサービスを識別した後は、次の基準に照らし合わせて設計を検証します。After you identify the microservices in your application, validate your design against the following criteria:

  • 各サービスが 1 つの役割を持っていること。Each service has a single responsibility.
  • サービス間で頻繁な呼び出しが行われないこと。There are no chatty calls between services. 機能を 2 つのサービスに分割したことによってそれらの間で過度に頻繁に呼び出しが行われる場合、それらの関数が同じサービスに属すことを示している可能性があります。If splitting functionality into two services causes them to be overly chatty, it may be a symptom that these functions belong in the same service.
  • 各サービスが、独立して作業する小規模なチームで構築できるくらいに十分小さいこと。Each service is small enough that it can be built by a small team working independently.
  • 複数のサービスをロックステップでデプロイすることが必要になる相互依存関係がないこと。There are no inter-dependencies that will require two or more services to be deployed in lock-step. 常に、他のサービスを再デプロイすることなくサービスをデプロイできる必要があります。It should always be possible to deploy a service without redeploying any other services.
  • サービスが密結合されておらず、個別に展開できること。Services are not tightly coupled, and can evolve independently.
  • そうすれば、サービスの境界でデータの一貫性や整合性の問題が発生することはありません。Your service boundaries will not create problems with data consistency or integrity. 場合によっては、単一のマイクロサービスに機能を収めることによってデータの整合性を維持することが重要になります。Sometimes it's important to maintain data consistency by putting functionality into a single microservice. ただし、強力な一貫性が本当に必要かどうかを検討する必要があります。That said, consider whether you really need strong consistency. 分散システムで最終的な整合性に対処するための戦略があり、多くの場合、サービスを分割するメリットの方が、最終的な整合性を管理する難しさより勝ります。There are strategies for addressing eventual consistency in a distributed system, and the benefits of decomposing services often outweigh the challenges of managing eventual consistency.

何よりもまず、実際的であること、そしてドメインベースの設計は反復プロセスであることを忘れないようにすることが重要です。Above all, it's important to be pragmatic, and remember that domain-driven design is an iterative process. 判断に迷うときは、より粒度の粗いマイクロサービスで始めるようにします。When in doubt, start with more coarse-grained microservices. 1 つのマイクロサービスを 2 つの小さいサービスに分割する方が、既存の複数のマイクロサービスの機能をリファクタリングするより簡単です。Splitting a microservice into two smaller services is easier than refactoring functionality across several existing microservices.

例:ドローン配送アプリケーションのマイクロサービスを定義するExample: Defining microservices for the Drone Delivery application

開発チームは 4 つの集計 (配送、パッケージ、ドローン、アカウント) と 2 つのドメイン サービス (スケジューラとスーパーバイザー) を識別したことを思い出してください。Recall that the development team had identified the four aggregates — Delivery, Package, Drone, and Account — and two domain services, Scheduler and Supervisor.

配送とパッケージは、マイクロサービスの明らかな候補です。Delivery and Package are obvious candidates for microservices. スケジューラとスーパーバイザーは、他のマイクロサービスによって実行されるアクティビティを調整するので、これらのドメイン サービスをマイクロサービスとして実装するのは当然のことです。The Scheduler and Supervisor coordinate the activities performed by other microservices, so it makes sense to implement these domain services as microservices.

ドローンとアカウントが興味深いのは、他の境界付けられたコンテキストに属していることです。Drone and Account are interesting because they belong to other bounded contexts. 1 つのオプションは、スケジューラでドローンとアカウントの境界付けられたコンテキストを直接呼び出すというものです。One option is for the Scheduler to call the Drone and Account bounded contexts directly. もう 1 つのオプションは、発送の境界付けられたコンテキストの内部にドローンとアカウントのマイクロサービスを作成することです。Another option is to create Drone and Account microservices inside the Shipping bounded context. これらマイクロサービスは、発送コンテキストにより適した API またはデータ スキーマを公開することにより、境界付けられたコンテキストの間を仲介します。These microservices would mediate between the bounded contexts, by exposing APIs or data schemas that are more suited to the Shipping context.

ドローンとアカウントの境界付けられたコンテキストの詳細はこのガイドの範囲外なので、参照実装ではこれらのモック サービスを作成しました。The details of the Drone and Account bounded contexts are beyond the scope of this guidance, so we created mock services for them in our reference implementation. ただし、この状況では次のような要因を考慮する必要があります。But here are some factors to consider in this situation:

  • 他の境界付けられたコンテキストを直接呼び出すとどのようなネットワーク オーバーヘッドがあるか。What is the network overhead of calling directly into the other bounded context?

  • 他の境界付けられたコンテキストのデータ スキーマがこのコンテキストに適しているか、またはこの境界付けられたコンテキストに合わせて調整されたスキーマを作成する方がよいか。Is the data schema for the other bounded context suitable for this context, or is it better to have a schema that's tailored to this bounded context?

  • 他の境界付けられたコンテキストはレガシ システムか。Is the other bounded context a legacy system? そうである場合は、破損対策レイヤーとして機能するサービスを作成し、レガシ システムと最新のアプリケーションの間の変換を行うことが考えられます。If so, you might create a service that acts as an anti-corruption layer to translate between the legacy system and the modern application.

  • チームはどのような構造か。What is the team structure? 他の境界付けられたコンテキストを担当するチームと簡単に通信できるか。Is it easy to communicate with the team that's responsible for the other bounded context? そうでない場合は、2 つのコンテキストの間を仲介するサービスを作成すると、チーム間の通信コストの削減に役立つ場合があります。If not, creating a service that mediates between the two contexts can help to mitigate the cost of cross-team communication.

これまで、機能以外の要件については考慮してきませんでした。So far, we haven't considered any non-functional requirements. アプリケーションのスループット要件を考慮し、開発チームはクライアント要求のインジェストを行うインジェスト マイクロサービスを別に作成することを決定しました。Thinking about the application's throughput requirements, the development team decided to create a separate Ingestion microservice that is responsible for ingesting client requests. このマイクロサービスは、着信した要求を処理のためのバッファーに入れることで、負荷平準化を実装します。This microservice will implement load leveling by putting incoming requests into a buffer for processing. スケジューラは、バッファーから要求を読み取って、ワークフローを実行します。The Scheduler will read the requests from the buffer and execute the workflow.

機能以外の要件により、チームは 1 つの追加サービスを作成することにしました。Non-functional requirements led the team to create one additional service. これまでのサービスはすべて、パッケージのスケジューリングと配送をリアルタイムで行うプロセスに関するものでした。All of the services so far have been about the process of scheduling and delivering packages in real time. しかし、システムでは、データ分析のための長期的な記憶域にすべての配送の履歴を格納する必要もあります。But the system also needs to store the history of every delivery in long-term storage for data analysis. チームは、これを配送サービスで行うことを検討しました。The team considered making this the responsibility of the Delivery service. ただし、データ記憶域の要件は、履歴分析と処理中の操作ではまったく異なります (「データに関する考慮事項」を参照)。However, the data storage requirements are quite different for historical analysis versus in-flight operations (see Data considerations). そのため、チームは配送履歴サービスを別に作成することにしました。このサービスは、配送サービスからの DeliveryTracking イベントをリッスンし、長期的な記憶域にイベントを書き込みます。Therefore, the team decided to create a separate Delivery History service, which will listen for DeliveryTracking events from the Delivery service and write the events into long-term storage.

次の図は、この時点での設計を示したものです。The following diagram shows the design at this point:

設計の図

次のステップNext steps

この時点で、自分の設計における各マイクロサービスの目的と機能を明確に理解しているはずです。At this point, you should have a clear understanding of the purpose and functionality of each microservice in your design. これでシステムを設計できます。Now you can architect the system.