Author | repairCopy the code

The back view

Microservices have become very popular in recent years, and many companies are considering microservices architecture. At the same time, with the development of Docker container technology and automated operation and maintenance technology, microservices become easier to manage, which gives a good opportunity for the development of microservices architecture. Breaking up services is a hot topic on the micro service road. What principles should we follow to split the existing business? Is the finer the better? Let’s talk about the strategy and principles for service unbundling.

What is the purpose of the split?

Before we talk about how to split, we need to understand the purpose of the split so that we don’t forget the original purpose in the subsequent split. The essence of splitting is to simplify complex problems, so what complexity problems did we encounter during the monolithic architecture phase? First of all, let’s recall why we chose the single architecture. At the beginning of the e-commerce project, we only hoped to set up the project as soon as possible, so as to facilitate the early launch of the product into the market for quick verification. At the initial stage of development, this architecture does bring great convenience to development and operation and maintenance, mainly reflected in:

  • Development is simple and direct, code and project centralized management.
  • When troubleshooting problems, you only need to troubleshoot this application, which is more targeted.
  • Only one project needs to be maintained, saving the labor cost of system maintenance.

However, with more and more functions and larger development teams, the defects of single architecture are gradually reflected, mainly in the following aspects: At the technical level, the number of database connections becomes the bottleneck of application server expansion, because the number of clients connected to MySQL is limited. In addition, the single structure increases the cost of r&d and inhibits the improvement of R&D efficiency. For example, the company’s vertical e-commerce systems team will be split into different groups by line of business. When so many small teams work together to maintain a single set of code and a single system, problems arise in coordination. There is little communication between different teams. If a team needs a function to send short messages, some r&d students will think that the fastest way is not to ask other teams if they have one, but to write one by themselves. However, this idea is not appropriate, which will lead to repeated development of functions and services. Because code is deployed together and everyone commits to the same code base, code conflicts are inevitable; At the same time, there is a lot of coupling between functions, so you can change only a small amount of logic and make other functions unavailable, which requires regression of the whole function during testing, extending the delivery time. Modules depend on each other, and a mistake made by a member of a small team may affect the services maintained by other teams, which has a great impact on the overall system stability. Finally, the individual architecture also has a great impact on the operation and maintenance of the system. Imagine starting a project with a few thousand lines of code that takes only a minute to build, and you have the flexibility to go online frequently to fix problems. But when your system scales to hundreds of thousands or even millions of lines of code, a build process including compilation, unit testing, packaging, and uploading to a formal environment can take up to ten minutes, and any small change requires the entire project to be built, making the process of on-line change very inflexibles. All these problems can be solved by microservitization. To help you better understand this, I’ve attached a table (from evolving Cloud Native: The Best microservices in the Cloud Native Architecture) to help you visualize the purpose of the split.

How should the timing of the split be decided?

At the beginning of the product, the single architecture should take precedence. In a new field, it is difficult to have a clear understanding of the business at the beginning, and it usually becomes stable gradually after a period of time. If the separation is premature, it will lead to unreasonable boundary separation or excessive separation, which will affect productivity. In many cases, it is easier to carve out services from an existing monolithic architecture than to build microservices from the start. At the same time, the company’s products have not been verified by the market and may fail, so the investment risk will be relatively high. In addition, in the case of resource constraints, many advantages of using microservices architecture are not reflected, but performance disadvantages will be more obvious. As shown in the figure below. When the business complexity reaches a certain level, the cost of microservice architecture will be advantageous. Not all scenarios are suitable for microservice architecture, and the division of services should be gradually and continuously evolve. In the early stage of the product, when the service complexity is not high, the single architecture should be adopted as much as possible.

As the company’s business model was verified, and the products won the market recognition, in order to speed up the iterative efficiency quickly occupy the market, the company began to introduce more to the development of students, then the complexity of the system becomes more and more high, in monomer appears contradiction between application and team size, r&d efficiency rise but not fall. The intersections in the figure above indicate that the business has reached a certain level of complexity, individual applications are no longer able to meet the needs of business growth, and r&d efficiency begins to decline. At this point, it is time to consider service separation. This is a point for the architect to weigh. In my company, it was only when the team size reached 100 people that it considered servitization. When we know when to break it up, can we just hit the ground running? No, micro service break up the ground to supporting infrastructure ready ahead of time, such as service description, service registry, service framework, monitoring, tracking services, service management and so on several big basic components, each of these components are short of one cannot, each component and include many technical threshold, such as container technology, continuous deployment, enterprise and other related concepts, And the reserve of talent and the change of ideas. Microservice is not only the upgrade of technology, but also the change of development mode, organizational structure and development concept.

At this point, when to split microservices, the overall summary is as follows:

  1. Business scale: the business model has been verified by the market, and it needs to further accelerate its pace to occupy the market quickly. At this time, the business scale becomes larger and larger, and it is divided by product life cycle (introduction period, growth period, maturity period and decline period), which is generally in the growth period. If it is an initiation period, try to use a single architecture.
  2. Team size: Usually when the team reaches 100 people.
  3. Technology pool: Domain-driven design, registry, configuration center, logging system, continuous delivery, monitoring system, distributed timing task, CAP theory, distributed call chain, API Gateway, etc.
  4. Talent pool: architects proficient in micro-service implementation experience and corresponding development students.
  5. R & D efficiency: R & D efficiency has declined significantly. Specific problems are mentioned in the purpose of the above split.

What guidelines should you stick to when splitting up?

1. High cohesion and low coupling of internal functions of a single service

In other words, each service only performs tasks within its own responsibility, and assigns functions that are not its responsibility to other services.2. Closure Principle (CCP)The closure principle of microservices is that when we need to change a microservice, all dependencies are within the component of the microservice, and no other microservices need to be modified.3. Service autonomy and interface isolationTry to eliminate the strong dependence on other services to reduce communication costs and improve service stability. Services are isolated through standard interfaces that hide internal implementation details. This allows services to be independently developed, tested, deployed, run, and continuously delivered on a service basis.4. Continuous evolutionIn the early stages of service unbundling, it’s really hard to determine what the service is going to be. From micro service the words, the granularity of the seemingly should be small enough, but the service would bring more problems, service quantity rapid growth leads to a dramatic increase in architecture complexity, development, testing, operational, it is difficult to quickly adapt to, can lead to failure rate greatly increased, and reduced availability, not necessary, should be gradual, continue to evolve, To avoid the explosive growth of the number of services, which is equivalent to the effect of grayscale release, first take out several less important functions to split a service to do the test, if there is a failure, you can reduce the scope of failure.5. The process of splitting should avoid affecting the daily functional iteration of the productThat is to say, to do product function iteration, while completing the separation of services. For example, we should first divest independent boundary services (such as SMS service, etc.), reduce the impact of the split on the existing business from non-core services, and also give the team a chance to practice and try and error. At the same time, if two services have dependencies, the dependent service will be split first.6. Define extensible service interfacesSince services are deployed as separate processes, communication between services is no longer an in-process method call but a cross-process network communication. The definition of the service interface under this communication model needs to be extensible, or it will cause unexpected errors when the service changes. For example, the interface of microservice changed three parameters to four due to the upgrade, which leads to a large number of errors reported by the caller after it goes online. It is recommended that the parameter type of the service interface should be encapsulation class, so that it is not necessary to change the interface signature by adding parameters, but only need to add fields in the class7. Avoid circular and bidirectional dependenciesTry not to have circular or bidirectional dependencies between services because they indicate that our functional boundaries are not clear or that common functionality is not sinking.

Step by step merger As you gradually deepen your understanding of the business domain, or the logic of the business itself changes greatly, or the previous separation was not considered clearly, resulting in the service boundary after the separation becomes more and more chaotic, then it is necessary to comb out the domain boundary again, and constantly correct the rationality of the separation.

Is the granularity of separation as fine as possible?

At present, many traditional monomer applications are upgrading microservices architecture. If the granularity is too fine, it will increase the operation and maintenance complexity, and if the granularity is too large, it will not work. Then how to balance the granularity in the transformation process?

1. Principle of bow and arrow Balanced split granularity can be balanced from two aspects, one is the complexity of business development, the other is the number of team size. As shown above, it is like a bow and arrow, and only when the business complexity and team size are large enough, the sword of service separation granularity will fly further and have the most power. Goods and services like electricity, for instance, when we put the goods from the split in the monomer, while in terms of goods and services itself, logic is not complicated enough to the point of 2 ~ 3 people couldn’t maintain, at this moment we don’t need to continue to remove the goods and services more thin, but with the development of the business, the business logic of commodity is more and more complicated, It may serve multiple platforms of the company at the same time. At this time, you will find that the problems faced by the commodity service itself are basically the same as those faced by the single architecture stage. At this stage, we need to disassemble the commodity into more fine-grained services, such as inventory service, price service, category service, commodity basic information service and so on.

Although the complexity of the business has been met, if the company does not have enough manpower (late recruitment or high turnover of staff), it is better not to split the service, which will lead to more problems due to the shortage of manpower, such as a sharp decline in r&d efficiency (a development responsible for the number of services that do not match it). This leads to another question, how many development and maintenance is reasonable for a microservice? I quote a classic discussion by Li Yunhua in “Learning architecture from scratch” to solve this problem. 2. The principle of three Musketeers why is it rational for three people to allocate one service? Not four, not two? First of all, in terms of the system scale, three people are responsible for developing a system, and the complexity of the system is just enough that everyone can fully understand the whole system and be able to divide the labor. If two people develop a system, the complexity of the system is not enough, the developers may feel unable to reflect their technical strength; With four or more people working on a system, the complexity of the system prevents developers from understanding the details of the system in depth. Secondly, from the perspective of team management, three people can form a stable backup. Even if one person takes a vacation or transfers to other systems, the remaining two people can still support him. If there are two people, the remaining one is under a lot of pressure; If it’s one person, it’s a single point, the team doesn’t have a backup, it’s dangerous in some cases, what if this person is on vacation and something goes wrong? Finally, from the perspective of technical improvement, a technical team of three people can not only form effective discussions, but also reach consensus quickly. If there are two people, they may insist on their own opinions, or the lack of experience of both people may lead to design defects. If it is a person, because no one to discuss technology with him, it is likely to fall into the blind zone of thinking, leading to major problems; If it’s four or more people, it’s possible that some of the people involved aren’t really involved and are just getting the job done. The principle of “Three Musketeers” is mainly applied in the design and development stage of micro-services. If the micro-services have been stable after a period of development and are in the maintenance stage without too much development, it is ok for one person to maintain one or even several micro-services on average. Of course, considering the problem of personnel backup, it is best to arrange two people to maintain each micro-service, and each person can maintain multiple micro-services. To sum up, the separation granularity is not the finer the better, the granularity needs to comply with the principle of bow and arrow and the three musketeers principle.

What are the split strategies?

The resolution strategy can be divided into functional and non-functional dimensions. The functional dimension is to define the boundaries of services, and the non-functional dimension mainly considers six aspects including scalability, reusability, high performance, high availability, security, and heterogeneity. Let’s talk about it in detail.

The functional dimension mainly divides the business boundary clearly, the main design method can use DDD (the theoretical knowledge about DDD can refer to other online materials), the strategic design of DDD will establish the domain model, which can guide the separation of microservices, mainly divided into four steps:

  • The first step is to identify domain objects such as domain entities and value objects.
  • The second step is to find the aggregation root and build the aggregation based on the dependencies of entities, value objects and the aggregation root.
  • The third step is to define the bounding context based on business and semantic boundaries.
  • Fourth, each bounded context can be split into a corresponding microservice, but some non-functional factors should also be considered.

Taking the e-commerce scenario as an example, the limiting context of transaction link division is shown in the left part of the figure below, and a microservice can be designed according to a limiting context. The disassembled microservice is shown in the right part of the figure below.

2. Non-functional Dimensions When we split by functional dimensions, it’s not all good. In most cases, we need to add other dimensions to further split to solve the problems caused by the single architecture.

  • Extensibility: to distinguish the variable with the same part of the system, the same part of the general is a mature, universal service function and become part of the changes are generally more, meet the need of business iterative expansibility function, we can be the same part of the split, as a common service, will become part of the independence of meet the needs of the personalized extension. At the same time, according to the 80/20 principle, the part of the system that changes frequently only accounts for about 20%, while the remaining 80% is basically unchanged or rarely changes. This split also solves the problem that too many releases affect the stability of mature services.

  • Reusability: Repetitive functions often occur in different services or services. For example, each service has functions such as authentication, traffic limiting, security, and log monitoring. These functions can be separated into independent services, that is, API gateways in microservices. For example, Didi has express and Shunwindmill services, both of which involve the function of order payment, so order payment can be separated as a universal service to serve the upper business. The diagram below:

  • High performance: Separates modules with high performance requirements or pressure to prevent services with high performance pressure from affecting other services. The most common way to split is related to specific performance bottlenecks, such as online shopping. The biggest performance pressure is the queuing function of the entrance, which can be separated into a service. At the same time, we can also split the product information based on read and write separation. For example, the commodity information of e-commerce mainly has a large number of read operations on the App end, but there is very little traffic in the business center on the write end. Therefore, read and write services with heavy traffic or core services can be separated into two services, one for reading and the other for writing. Based on performance and data consistency is another dimension split points, to consider for the strong and consistent data, belongs to the strong coupling, as far as possible in the same service (but sometimes because of various reasons to split, it requires a response mechanism to guarantee), weak consistency usually can be broken down into different services.

  • High availability: Split core services with high reliability requirements and non-core services with low reliability requirements, and then focus on ensuring high availability of core services. The split can be one or more core services, as long as the final number of services meets the principle of “three Musketeers”. For example, for merchant services, you can split a core service and a non-core service. The core service is accessed by the transaction service, and the non-core service is provided by the merchant center.

  • Security: Different services may be different requirements for information security, so the need to split, high security service for different deployment, such as setting up specific the DMZ to partition deployment of services, can be more targeted to meet the requirements of information security, can also reduce the firewall and other security equipment throughput and concurrency requirements, reduce cost, Improve efficiency.

  • Heterogeneity: For business scenarios that require a variety of development languages, functions in different languages can be separated to implement a single service.

The above methods of splitting are not multiple choices, but can be arranged and combined freely according to the actual situation. Meanwhile, the split is not only an architectural adjustment, but also an adaptive optimization in the organizational structure to ensure that the services are maintained by a relatively independent team.

Why merge services when they’re broken down?

The Ancient Greek philosopher Heraclitus once said, “You cannot step into the same river twice.” The state of everything changes over time. The same is true for online systems, even though one system is never exactly the same at different times. The granularity of the services now being split may be appropriate, but there is no guarantee that the granularity will always be correct.

Why services are dismantled, is to constantly adapt to the new stage of business development, the author here to make an analogy to see whether we are clear, dismantled is equivalent to our development code, the equivalent of the reconstruction of the code, why to reconstruct it, I believe you must know. The same goes for microservices, which may change over time as we learn more about the application space. For example, you might find that a particular decomposition is inefficient due to too much interprocess communication, so you have to group some services together. At the same time, the maintenance cost increases due to the mismatch between the number of personnel and the number of services, which is also an important reason for service consolidation. For example, due to the impact of the epidemic this year, many enterprises began to lay off a large number of employees and lost staff, but the number of services did not change, resulting in the imbalance between the number of services and personnel. One developer had to maintain the development of at least five services at the same time, which greatly reduced efficiency. Therefore, if the number of microservices is too large and resources do not match, it can be considered to merge multiple microservices into service packages and deploy them on one server, which can save the basic resource consumption during service operation and reduce the maintenance cost. It is important to note that although the service bundle runs in a process, the services within the service bundle still meet the microservice definition so that they can be quickly separated when they need to be reassembled at a future date. The service is merged into the service pack as follows:

Risks to be aware of during the split process

Whether the development team has enough experience to navigate the microservices technology stack is probably the first consideration. It is not necessary for the team to have complete experience in initiating a service split; it would be nice to have experts on the team. If not, there may be a need for thorough technical demonstration and rehearsals, or at least not unprepared battles. Avoid which simple first open which, which new business to go up, a service to say. Otherwise, you may stumble on some common distributed problems, such as insufficient server resources, operation and maintenance difficulties, chaotic calls between services, call retries, timeout mechanisms, distributed transactions, and so on. 2. Continuous correction We need to admit that our cognition is limited, and we can only work out a relatively appropriate solution based on the current business status and limited future prediction, rather than the so-called optimal solution. Any solution can only ensure that it provides relatively appropriate granularity and division principles at present. Always be prepared to be out of date and need to adjust again at the end of the future. Therefore, with the evolution of the business, we need to re-examine whether the division of services is reasonable. For example, if the service is too detailed, the efficiency of staff decreases and the probability of failure increases greatly, and the domain boundary needs to be re-demarcated.

3. Be a doer, not a theorist

In the specific how to split, also do not too entangled in whether it is appropriate, do not start how to know whether it is appropriate? If it is really not suitable after dismantling, it is good to readjust. Readjustment, you might say, is expensive. But in fact, the essence of the problem is whether there is a complete capability system for service-oriented architecture, such as service governance platform, data migration tool, data double write, etc. If there is, the cost of readjustment will not be too high.