16 | View: How to realize the collaboration of services and data at each layer of microservices?

Table of contents

Collaboration of services

1. Types of services

2. Service call

Cross-layer within microservice

Service calls between microservices

domain event driven

3. Encapsulation and composition of services

base layer

domain layer

application layer

user interface layer

 4. Service dependencies of two layered architectures

Service dependencies in a loosely layered architecture

 Strict layered architecture of service dependencies

data object view

base layer

domain layer

application layer

user interface layer

front-end application

Summarize


In the DDD layered architecture and microservice code model, we layer domain objects according to their attributes and dependencies, and define the corresponding code objects and code directory structure. The layered architecture determines the overall architecture of microservices. The main objects in microservices include services and entities, which work together to complete business logic.

How do these services and entities collaborate at each layer of microservices during operation? Today we will dissect the microservice based on the DDD layered architecture to see what its internal structure looks like.

Collaboration of services

1. Types of services

Let's start by reviewing services in a layered architecture. Microservices designed according to the layered architecture include Facade services, application services, domain services, and basic services. The main functions and responsibilities of each layer service are as follows.

  • Facade service: located in the user interface layer, including interface and implementation. It is used to process the Restful request sent by the user and parse the configuration file entered by the user, etc., and pass the data to the application layer. Or after obtaining the application layer data, assemble DO into DTO, and transmit the data to the front-end application.
  • Application service: located in the application layer. It is used to express application and user behavior, responsible for service combination, orchestration and forwarding, responsible for processing the execution sequence of business use cases and result assembly, and providing coarse-grained services externally.
  • Domain service: located in the domain layer. The domain service encapsulates the core business logic and realizes the core domain logic that requires the cooperation of multiple entities. It combines or orchestrates the business logic of multiple entities or methods, or encapsulates entity methods in a strict layered architecture, and provides domain services for application layer calls.
  • Basic service: located at the base layer. Provide basic resource services (such as database, cache, etc.), realize the decoupling of each layer, and reduce the impact of external resource changes on business application logic. Basic services are mainly warehousing services, which provide basic resource services through dependency inversion. Both domain services and application services can call storage service interfaces to achieve data persistence through storage services.

2. Service call

Let's take a look at the picture below. Microservice service calls include three main scenarios: cross-layer service calls within microservices, service calls between microservices, and domain event-driven.

Cross-layer within microservice

The service call microservice architecture often adopts the design pattern of front-end and back-end separation, and front-end applications are deployed independently. The front-end application calls the Facade service published on the API Gateway, and the Facade is directed to the application service. As a service organization and orchestrator, application service has two paths for its service invocation:

  • The first is that application services call and assemble domain services. At this point, domain services will assemble entities and entity methods to implement core domain logic. The domain service obtains the persistent data object through the storage service and completes the entity data initialization.
  • The second is that the application service directly calls the storage service. This method is mainly aimed at accessing basic layer data such as caches and files. This type of data is mainly for query operations without much domain logic, does not go through the domain layer, and does not involve database persistent objects.

Service calls between microservices

Application services between microservices can be accessed directly or through an API gateway. Due to cross-microservice operations, when adding and modifying data, you need to pay attention to distributed transactions to ensure data consistency.

domain event driven

Domain event-driven includes events within microservices and between microservices. The asynchronous processing between aggregates is completed through the event bus (EventBus) in the microservice. The communication between microservices is done through message middleware. The asynchronous domain event-driven mechanism is an indirect service access method.

After the application service business logic processing is completed, if a domain event occurs, the event publishing service can be called to complete the event publishing. When receiving the subscribed topic data, the event subscription service will call the event processing domain service to complete further business operations.

3. Encapsulation and composition of services

Let's take a look at the picture below. Microservice services are encapsulated, composed, and exposed from the domain layer upwards.

base layer

The service form of the basic layer is mainly warehousing services. Storage service includes interface and implementation. The storage interface service is called by the application layer or the domain layer service, and the storage realizes the service and completes the persistence or data initialization of the domain object.

domain layer

The domain layer implements core business logic and is responsible for expressing domain model business concepts, business status and business rules. The main service forms are entity methods and domain services.

The entity adopts the hyperemia model, and implements all business logic related to the entity within the entity class, and the implementation form is a method in the entity class. An entity is the atomic business logic unit of a microservice. When designing, we mainly consider the attributes and business behavior of the entity itself, and realize the core basic capabilities of the domain model. There is no need to think too much about external operations and business processes, so as to ensure the stability of the domain model.

DDD advocates a rich domain model, as far as possible to attribute business logic to entity objects, and design the parts that cannot be attributed as domain services. Domain services assemble and orchestrate multiple entities or entity methods to implement complex core business logic across multiple entities.

For a strictly layered architecture, if the method of a single entity needs to be exposed to the application layer, it needs to be encapsulated by the domain service before it can be exposed to the application service.

application layer

The application layer is used to express the behavior of applications and users, responsible for the combination, orchestration and forwarding of services, the execution order of business use cases and the assembly of results, the coordination of services and data between different aggregates, and the release of events between microservices and subscribe.

The internal functions of microservices are exposed externally through application services, so that the complexity of the core business logic of the domain layer and the internal implementation mechanism can be hidden. The main service forms of the application layer are: application service, event publishing and subscription service.

The services used for composition and orchestration in application services are mainly derived from domain services, and can also be application services of external microservices. In addition to completing the combination and orchestration of services, functions such as security authentication, authority verification, preliminary data verification, and distributed transaction control can also be completed within the application service.

In order to achieve decoupling between aggregates in microservices, service calls and data interactions between aggregates should be done through application services. In principle, we should prohibit the direct call of domain services between aggregates and the data table association between aggregates.

user interface layer

The user interface layer is a bridge for service access and data exchange between front-end applications and microservices. It handles the Restful request sent by the front end and parses the configuration files entered by the user, etc., and passes the data to the application layer. Or after obtaining the data of the application service, perform data assembly and provide data services to the front end. The main service form is Facade service.

Facade service is divided into interface and implementation. Complete service orientation, conversion and assembly of DO and DTO data, and realize conversion and exchange of front-end and application layer data. 

 4. Service dependencies of two layered architectures

Now let's review the DDD layered architecture. An important principle of the layered architecture is that each layer can only be coupled with the layer below it. According to the tightness of coupling, layered architecture can be divided into two types: strict layered architecture and loose layered architecture.

In a strictly layered architecture, any layer can only depend on the layer directly below it. In a loosely layered architecture, any layer can depend on any layer below it.

Let's analyze and compare these two layered architectures in detail.

Service dependencies in a loosely layered architecture

Let's take a look at the picture below. In the loose layered architecture, the entity methods and domain services of the domain layer can be directly exposed to the application layer and user interface layer. The service dependencies of the loose layered architecture can be quickly exposed to the upper layer without level-by-level encapsulation.

But it has some problems. The first is that it is easy to expose the implementation logic of the core business of the domain layer; the second is that when the entity method or domain service changes, because the service is called and combined by multi-layer services at the same time, it is not easy to find out It is inconvenient to notify all service callers which upper-level services call and combine it.

Let's look at another picture. In the loose layered architecture, the method of entity A is exposed to the user interface layer aFacade after the application layer is combined. The abDomainService domain service directly crosses the application layer and is exposed to the abFacade service of the user interface layer. Any lower-level service in a loosely layered architecture can be exposed to upper-level services.

 Strict layered architecture of service dependencies

Let's take a look at the picture below. In a strict layered architecture, each layer of services can only provide services to the immediately preceding layer. Although entities, entity methods, and domain services are all in the domain layer, entities and entity methods can only be exposed to domain services, and domain services can only be exposed to application services.

In a strictly layered architecture, if a service needs to be called across layers, the lower layer service needs to be encapsulated in the upper layer before it can provide the cross layer service. For example, entity methods need to provide services to application services, which need to be encapsulated into domain services.

This is because through encapsulation, you can avoid exposing the implementation of core business logic to the outside, encapsulate entities and methods into domain services, and avoid depositing too much core business logic that should belong to the domain layer in the application layer. become bloated. In addition, when a service changes, since the service is only called and combined by the service next to the upper layer, you only need to notify the next upper layer step by step. The service manageability is better than the loose layered architecture.

Let's still look at the picture, the A entity method needs to be encapsulated into the domain service aDomainService before it can be exposed to the application service aAppService. After abDomainService combines and encapsulates the methods of A and B entities, it is exposed to the application service abAppService.

data object view

There are many data objects in DDD, and these objects are distributed in different layers. They have different forms at different stages.

Let's first look at what types of data objects are in the microservice? How do they collaborate and transform?

  • The data persistence object PO (Persistent Object), which is mapped to the database structure one by one, is the data carrier in the process of data persistence.
  • The domain object DO (Domain Object), the entity of the microservice runtime, is the carrier of the core business.
  • Data Transfer Object (DTO) is used for data assembly and transmission between the front end and the application layer or microservices, and is the carrier of data transmission between applications.
  • The view object VO (View Object) is used to encapsulate the data of the specified page or component of the presentation layer.

Let's combine the following picture to see the responsibilities and conversion process of data objects at each layer of microservices.

base layer

The main object of the base layer is the PO object. We need to establish the mapping relationship between DO and PO first. When the DO data needs to be persisted, the storage service will convert the DO into a PO object to complete the database persistence operation. When the DO data needs to be initialized, the storage service obtains the data from the database to form a PO object, and converts the PO to DO to complete the data initialization.

In most cases there is a one-to-one correspondence between PO and DO. However, there are also many-to-many situations between DO and PO, and data reorganization is required during data conversion between DO and PO.

domain layer

The main object of domain layer is DO object. DO is the data and business behavior carrier of entities and value objects, carrying the basic core business logic. Through DO and PO conversion, we can complete data persistence and initialization.

application layer

The main objects of the application layer are DO objects. If it is necessary to call application services of other microservices, DO will be converted to DTO to complete data assembly and transmission across microservices. The user interface layer first completes the conversion from DTO to DO, and then the application service receives DO for business processing. If DTO and DO have a one-to-many relationship, DO data reorganization is required.

user interface layer

The user interface layer will complete the conversion between DO and DTO, and complete the data interaction and conversion between microservices and front-end applications. The Facade service assembles multiple DO objects, converts them into DTO objects, and completes data conversion and transmission to the front-end application.

front-end application

Front-end applications are mainly VO objects. The display layer uses VO for interface display, and the user interface layer and application layer use DTO objects for data interaction.

Summarize

Today we analyzed the collaborative relationship between microservice services and data under the DDD layered architecture. In order to achieve decoupling between aggregates and between layers of microservices, we define services and data objects with different responsibilities at each layer. In the process of software development, we need to strictly abide by the responsibility requirements of each layer of services and data, each according to its position, each perform its duties. Only in this way can the stability of the core domain model be guaranteed, and at the same time, it can flexibly respond to rapid changes in external requirements. 

Guess you like

Origin blog.csdn.net/zgz15515397650/article/details/131739116