Architect's advanced road - how to divide microservices

Table of contents

Microservice Partitioning Goals

Business, technology, team-oriented planning services

field check

Dependency DAG check

Distributed Transaction Checking

Performance Distribution Check

Stability (mutability) checks

Call Chain Check


 

Microservice Partitioning Goals

We often say that the reasonable division of services is the most important thing for the success of microservices. A reasonable service division should meet the following points:

  • The landing and maintenance of services that conform to the team structure depend on people, and rely on the executive team (including business, product, technology, testing, and operation and maintenance teams), so service settings must complement the team structure, and different implementations of the same system Teams often have different and reasonable service division schemes
  • Clear business boundaries Each service has clear responsibilities and boundaries, one service corresponds to one business, and most services are one-way dependent
  • Minimize changes. Adding or changing business has a clear service correspondence, or adding new services or expanding certain services. It is rare that this kind of ambiguity can be realized on this service or that service. In an ambiguous situation, under the premise of meeting the above conditions, the service affected by a change in a certain business requirement should be as few as possible
  • Maximize reuse Service reuse is a major advantage of servitization. Service settings should consider reuse scenarios. Under the premise of meeting the above conditions, service reuse should be maximized as much as possible.
  • Stable and concise performance The above conditions are more business-oriented. From a technical point of view, the core of service setting should focus on the impact on performance, whether it is stable, whether the structure is simple, whether to introduce additional middleware, etc.

Business, technology, team-oriented planning services

We must make it clear that services are not as detailed as possible. The first element of service division is to split from the business domain first, and then split from the technical perspective, and determine the relationship and boundary between services based on the size and capabilities of the team. After the service division is completed, check the following aspects to ensure the rationality of the service division.

1. Field inspection

Field inspection can provide directional guidance for our service division, making the service division clearer and more planned.

Domain common language inspection: to ensure that the same object described by production and research in a field is the same object, such as the inspection in quality inspection, Beijing’s "Luban Action" is both Luban inspection and post-inspection inspection due to historical reasons. The same kind of people are doing (quality inspection), and the western ones have differentiated Luban inspections and post-inspection inspections from the acceptance template. This is a typical example of inconsistent language descriptions in the same field, which leads to many problems. Errors in online data recording also caused statistics errors by students on the BI side, and repeated confirmation of the problem.

Bounded context check: divide the domain from the business characteristics to form sub-domains, and check whether the bounded context is divided reasonably. At the code level, whether to design inheritance relationships, entities, aggregations, value objects, domain services, etc. according to the bounded context. For example, many of our old and different services share the same DB. This phenomenon is not advocated in the microservice design or domain-driven design paradigm.

Domain Anti-Corruption Layer Check: Anti-corrosion layer isolation is not only about protecting its own domain model from code of other domain models, but also about separating different domains and making sure they stay separated in the future. Many of our current projects do not have a conceptual design for the anti-corrosion layer. As a result, most students just pile up the code during development and do not care about the integrity of the structure within the scope of the domain. In the end, the code style is very different, and the boundary of the system is confused.

        Due to the ambiguity of domain objects and domain context, rule generation business (actually a unified business) is split into different domain services, which brings many inconveniences:

  • If the rule business is not closed at the technical level, if there is a problem, it will be confirmed by multiple parties one by one. Only students who are familiar with the code will know whether the rule of "main material replenishment and return" is generated under the control of the supply chain service! ! ! But product students definitely don't know.
  • It is easy to miss the maintenance and handover of technical students in the later stage, and it is easy to miss the impact surface in the later iterative development.
  • Product iteration requires the support of different teams, but it is actually the same business, which is also unreasonable.

 

2. Rely on DAG check

        DAG is a directed acyclic graph in mathematics, which means that starting from any point will not return to this point, that is, there is no loop, and so should the dependencies of our services. Two-way or circular dependencies between services should be avoided as much as possible, otherwise it may lead to disastrous consequences. There is a directed cycle graph in the offline acceptance of the owner in the quality field. The first one in the figure below is the directed cycle graph problem that occurs when the owner initiates the offline applicant . Events occurred in the field of acceptance sheets, which increased the complexity of the interaction between systems, blurred system boundaries, and complicated call links. After domain boundary context re-planning and code optimization, the teaching system is delivered as shown in Figure 2. It can be seen that the boundaries are clear, system interaction is simplified, and call links are also reduced.

Figure 1

Figure II

3. Distributed transaction check

        The cost of distributed transaction calls is very high, and service splitting should try to avoid cross-service transactions, and combine them as much as possible. If it cannot be merged, give priority to TCC or MQ-based flexible transactions, and try to avoid transaction schemes such as 2PC that have a great impact on performance. TCC can completely replace 2PC, but the development cost is high, and all calling parties need to be modified synchronously to support Try, Confirm, and Cancel operations. In some scenarios, three-party services will be called, and their codes are not under our control. At this time, MQ can be considered for implementation. Asynchronous messaging and compensating transactions. Our business is relatively complex and there are many interactions and collaborations between systems, so distributed transactions are inevitable.

        To give a typical case, when the acceptance report is confirmed, the schedule time (scheduling field) will be modified synchronously due to delays, and the rectification work order (rectification field) will be recorded if there are unqualified items in the acceptance inspection, and the acceptance report will be modified synchronously as Confirm on behalf of the project manager or wait for the confirmation of the owner (in the field of acceptance form), if there is deferred payment, you need to confirm the deferred payment (in the field of service commitment), etc., so many field service calls must ensure success before the node is accepted. Formal transactions obviously cost a lot, which will inevitably lead to a lot of time-consuming interface and affect interface performance and system stability.

        Let's take a closer look at the characteristics of these areas. Among them, the scheduling field and the rectification field are the same field. When errors or modifications occur, the last submission must always prevail, so the field service must be "idempotent". It is best to reach an agreement at the product level. Compared with our rectification field, we need to reach an agreement with our product classmates at the production and research level: the last rectification submitted shall always prevail. We will record the rectification form submitted for this acceptance, and if there are repeated submissions, only the rectification submitted last time will be recorded. Of course, this is a solution in the case of low-frequency teaching in business scenarios. Everyone adopts the technical solution that is most suitable for their business scenarios according to their actual situation.

        The acceptance form field and deferred payment (service commitment field) are synchronous update operations, natural idempotent operations. In this business scenario, even if the submission is repeated, it will be updated to the target state, so there is no problem.

4. Performance distribution check

        For particularly resource-intensive operations, it should be as independent as possible. There should be no similar scenarios in this part of our system, as long as you know the paradigm in this area.

5. Stability (variability) check

        If there are stable and unstable modules in a service, the two should be split. This part has not been encountered in our business scenarios for the time being, and is basically deployed separately. In the quality field, the current acceptance template configuration occurs frequently and is divided into sub-field iterations separately. The change of the acceptance template configuration will not affect the acceptance application. Layer, everyone can pay attention to the impact of this aspect when designing the domain division system.

6. Call chain check

        Inter-service calls consume IO and are not easy to track. The length of the call link should be controlled. Through the call link between services, it is possible to clearly discover the call of historical invalid code, the invalid logic generated by iterative search of requirements, as well as hidden repeated calls, circular dependencies, and system optimization points, etc. The following figure is a case of acceptance submission. Due to the long iteration time, there are many discarded logics that have not been deleted. The code is bloated, not to mention calling the interfaces of other services and sending messages, all of which are resource costs. If you can sort out the code in time and make it clean The reliability has been improved, the maintenance cost has been reduced, and the stability of all services has also been improved.

Guess you like

Origin blog.csdn.net/lly576403061/article/details/131602882