Introduction to With the increase in project functions and scale, the shortcomings of the monolithic architecture also appear, and the microservice split can solve these problems.
Author: Xiuzhi
background
Microservices have become popular in recent years. The R&D personnel of many companies are considering the microservice architecture. At the same time, with the development of Docker container technology and automated operation and maintenance and other related technologies, microservices have become easier to manage, which gives the microservice architecture Good development opportunities.
On the way to do microservices, splitting services is a hot topic. What principles should we follow to split the existing business? Should it be as fine as possible? Next, let's talk about the strategy and principles of service splitting.
What is the purpose of the split?
Before introducing how to split, we need to understand what the purpose of the split is, so as not to forget the original purpose in the subsequent splitting process.
The essence of splitting is to simplify complex issues. So what complexity issues did we encounter in the monolithic architecture stage? First of all, think back and forth why the single architecture was chosen. When the e-commerce project just started, we only hope that the project can be set up as soon as possible, so that the product can be put on the market earlier for rapid verification. In the early stage of development, this architecture did bring great convenience to development and operation and maintenance, mainly reflected in:
- Development is simple and straightforward, code and project centralized management
- When troubleshooting, you only need to check this application, which is more targeted
- Only need to maintain one project, saving the labor cost of maintaining system operation
But with more and more functions, the scale of the development team is getting bigger and bigger, and the defects of the monolithic architecture are slowly manifesting, mainly in the following aspects.
At the technical level, the number of database connections has become the bottleneck of application server expansion, because the number of clients connecting to MySQL is limited.
, the monolithic architecture increases the cost of R&D and inhibits the improvement of R&D efficiency. example, the company's vertical e-commerce system team will be divided into different groups according to business lines. When so many small teams maintain a set of code and a system together, problems will arise in the process of cooperation. There is little communication between different teams. If a team needs a function to send text messages, then some R&D students will think that the fastest way is not to ask other teams if they have ready-made ones, but to write one by themselves, but this idea is not Appropriate, it will cause repeated development of functional services. Because the code is deployed together, everyone submits the code to the same code base, code conflicts are unavoidable; at the same time, the coupling between functions is serious, maybe you just changed a small logic but other functions are not available, so you need to test The return of the overall function has extended the delivery time. Modules depend on each other. If a member of a small team makes a mistake, it may affect the services maintained by other teams, which greatly affects the overall system stability.
Finally, the monolithic architecture will also have a great impact on the operation and maintenance of the system. Imagine that at the beginning of the project, your code may only have a few thousand lines, and it only takes one minute to build each time. Then you can quickly and flexibly go online to change and fix problems. But when your system is expanded to hundreds of thousands or even millions of lines of code, the process of a build includes compiling, unit testing, packaging and uploading to the formal environment. It may take up to ten minutes and any small amount of time. Modifications require the construction of the entire project, and the process of online changes is very inflexible.
And these problems can be solved by micro-service splitting.
In order to facilitate your better understanding of this, I have attached a table here (_content source: "Continuously evolving Cloud Native: the best microservices under the cloud native architecture" book_), which can help you more intuitively Recognize the purpose of the split.
How to decide when to split?
In the early stage of the product, the monolithic architecture should be given priority. Because in the face of a new field, it is difficult to understand the business clearly at the beginning. It is often after a period of time that it can gradually stabilize. If the split is too early, the boundary split will be unreasonable or the split will be too fine. Will affect productivity. In many cases, gradually dividing services from an existing monolithic architecture is much simpler than building microservices from the beginning. At the same time, the company's products have not been verified by the market and may fail, so the risk of this investment will also be relatively high.
In addition, in the case of limited resources, many advantages of adopting a microservice architecture cannot be reflected, and the performance disadvantages will be more obvious. As shown below. When the business complexity reaches a certain level, the cost consumed by the micro-service architecture will show its advantages. Not all scenarios are suitable for adopting the micro-service architecture. The division of services should be carried out gradually and continuously evolve. In the early stage of the product, when the business complexity is not high, the monolithic architecture should be adopted as much as possible.
As the company’s business model is gradually verified, and products are recognized by the market, in order to speed up the iterative efficiency of products and quickly occupy the market, the company began to introduce more developers, and the complexity of the system will become more and more. If it is high, there will be a contradiction between the single application and the team size, and the R&D efficiency will not increase but decrease. The intersection in the above figure shows that the business has reached a certain level of complexity, the single application can no longer meet the needs of business growth, and the R&D efficiency has begun to decline, and this is the time to consider service splitting. This point requires the architect to weigh. The author's company only considers servicing when the team size reaches 100 people.
When we know when to split, can we directly land? No, the implementation of microservice splitting requires the preparation of supporting infrastructure in advance, such as service description, registration center, service framework, service monitoring, service tracking, service governance and other basic components. Each of the above components is indispensable , Each component deployment also includes many technical thresholds, such as container technology, continuous deployment, DevOps and other related concepts, as well as talent reserves and changes in concepts. not only technology upgrades, but also development methods and organizational structures. , Change of development concept.
So far, when to split the microservices, the overall summary is as follows:
- Business scale: The business model has been validated by the market and needs to be further accelerated to quickly occupy the market. At this time, the scale of the business becomes larger and larger, divided according to the product life cycle (introduction period, growth period, maturity period, and decline period). Time is generally in the growth stage. If it is the introduction period, try to use a single structure.
- Team size: Usually when the team reaches 100 people.
- Technical reserves: domain-driven design, registration center, configuration center, log system, continuous delivery, monitoring system, distributed timing tasks, CAP theory, distributed call chain, API gateway, etc.
- Talent reserve: architects who are proficient in the implementation of microservices and corresponding development students.
- R&D efficiency: R&D efficiency has dropped significantly. For specific issues, please refer to the above-mentioned split objectives.
What guiding principles should be adhered to when splitting?
1. High cohesion and low coupling of internal functions of a single service
That is to say, each service only completes the tasks within its own responsibility, and assigns other services to other services for functions that are not its own responsibility.
2. Closure Principle (CCP)
The closure principle of microservices is that when we need to change a microservice, all dependencies are in the components of this microservice, and there is no need to modify other microservices.
3. The principle of service autonomy and interface isolation
Try to eliminate the strong dependence on other services, which can reduce communication costs and improve service stability. Services are isolated through standard interfaces, hiding internal implementation details. This allows services to be independently developed, tested, deployed, and run, and continuously delivered as a service unit.
4. Principle of continuous evolution
In the early days of service splitting, it is actually difficult to determine what the service will be split into. From the perspective of the words microservices, the granularity of services seems to be small enough, but more services will also cause problems. The rapid growth of the number of services will bring about a sharp increase in the complexity of the architecture, development, testing, operation and maintenance, etc. It is difficult to adapt quickly, which will lead to a significant increase in failure rate and reduced availability. Non-essential situations should be divided gradually and continuously evolved to avoid explosive growth in the number of services. This is equivalent to the effect of gray release. First, take a few less important The function of splitting out a service for testing, if there is a failure, you can reduce the scope of the failure.
5. The process of splitting try to avoid affecting the daily function iteration of the product
In other words, it is necessary to iterate on product functions while completing the service-oriented split. For example, prioritize the separation of relatively independent boundary services (such as SMS services), starting from non-core services to reduce the impact of the separation on existing businesses, and also give the team an opportunity for practice and trial and error. At the same time, when there is a dependency between two services, the dependent service is split first.
6. The definition of service interface must be extensible
After the service is split, because the service is deployed as an independent process, the communication between services is no longer a method call within the process but a cross-process network communication. The definition of the service interface under this communication model must be extensible, otherwise unexpected errors will be caused when the service changes. For example, due to the upgrade of the microservice interface, the previous three parameters were changed to four. After going online, the caller reported a large number of errors. It is recommended that the parameter type of the service interface should be an encapsulation class, so that if you add parameters, you do not need to change the signature of the interface. , And you only need to add fields to the class
7. Avoid circular dependency and two-way dependency
Try not to have circular dependencies or two-way dependencies between services. The reason is that the existence of this situation indicates that our functional boundaries are not clearly distinguished or that there are common functions that have not sunk.
8. Phased merger
As you gradually deepen your understanding of the business domain or the logic of the business itself has undergone major changes, or the previous split was not considered very clearly, the service boundary after the split has become more and more chaotic. At this time, It is necessary to reorganize the boundaries of the field and continuously correct the rationality of the split.
Is the granularity of the split the finer the better?
At present, many traditional monolithic applications are upgraded to the microservice architecture. If the split granularity is too fine, it will increase the complexity of operation and maintenance, and the granularity is too large and it will not be effective. Then how to balance the split granularity in the transformation process?
Bow and arrow principle
Balancing the split granularity can be weighed from two aspects, one is the complexity of business development, and the other is the number of people in the team. As shown in the figure above, it is like a bow and arrow. Only when the business complexity and the number of teams are large enough, the service split granularity of the shot will fly farther and exert the greatest power.
For example, e-commerce commodity services. When we split the commodity from a large unit, the logic of the commodity service itself is not complex enough to the point where 2~3 people can’t maintain it. At this time, we don’t. It is necessary to continue to break down the goods and services in more detail, but with the development of the business, the business logic of the goods becomes more and more complicated, and it may serve multiple platforms of the company at the same time. At this time, you will find the problems faced by the goods and services themselves. The problems faced in the system architecture stage are basically the same. At this stage, we need to disassemble the products into more fine-grained services, such as inventory services, price services, category services, commodity basic information services, and so on.
Although the complexity of the business has been satisfied, if the company does not have enough manpower at this time (recruitment is not timely or there are more employee changes), it is best not to split the service. The split will cause more problems due to lack of manpower, such as research and development. The efficiency has dropped significantly (a developer is responsible for the number of services that do not match it). Here is another question. How many development and maintenance does a microservice need to be more rational? I quoted a classic exposition by Mr. Li Yunhua in "Learning Architecture from Scratch" to solve this problem.
Three Musketeers Principle
Why is it more rational for three people to allocate one service? Instead of 4 or 2?
First of all, in terms of system scale, three people are responsible for developing a system, and the complexity of the system just reaches the granularity that everyone can fully understand the entire system and can divide labor; if two people develop a system, the complexity of the system is not enough , Developers may feel unable to reflect their technical strength; if four or more people develop a system, the complexity of the system will not allow the developers to have a deep understanding of the details of the system.
Secondly, from the perspective of team management, 3 people can form a stable backup. Even if 1 person takes a vacation or is deployed to other systems, the remaining 2 people can still support it; if it is 2 people, the remaining 1 person will be under great pressure after 1 is selected. ; If it is one person, this is a single point, and the team does not have a backup. In some cases, it is very dangerous. What if this person is on vacation and the system has a problem?
Finally, from the perspective of technology improvement, a three-person technical team can not only form effective discussions, but also quickly reach an agreement; if it is two people, it may appear that they adhere to each other's opinions, or both of them have insufficient experience. Design flaws; if it is one person, because no one has technical discussions with him, it is likely to fall into a blind area of thinking and cause major problems; if it is four or more people, some people involved may not participate seriously, but just complete the task.
The principle of "Three Musketeers" is mainly applied in the microservice design and development stage. If the microservice is relatively stable after a period of development and is in the maintenance period, and there is no need for too much development, then one person maintains one microservice on average Even a few microservices are fine. Of course, taking into account the issue of personnel backup, it is best to arrange two personal maintenance for each microservice, and each person can maintain multiple microservices.
sum up, the granularity of separation is not as fine as possible, and the granularity needs to comply with the principle of bow and arrow and the principle of three musketeers.
What are the split strategies?
The split strategy can be considered in terms of functional and non-functional dimensions. The functional dimension is mainly to clearly divide the boundaries of the business. The non-functional dimension mainly considers six points including scalability, reusability, high performance, high availability, security, and heterogeneity. . Next, I will introduce it in detail.
Functional dimension
The functional dimension is mainly to divide the business boundary clearly. The main design method adopted can use DDD (for the theoretical knowledge of DDD, please refer to other information on the Internet). The strategic design of DDD will establish a domain model, which can guide the split of microservices through the domain model. Mainly divided into four steps:
- The first step is to find domain objects such as domain entities and value objects.
- The second step is to find out the aggregate root, and establish the aggregate according to the dependency relationship between the entity, value object and the aggregate root.
- The third step is to define the bounding context based on factors such as business and semantic boundaries.
- In the fourth step, each bounded context can be split into a corresponding microservice, but some non-functional factors must also be considered.
Taking the e-commerce scenario as an example, the boundary context of the transaction link is divided into the left part of the figure below. According to a boundary context, a microservice can be designed. The disassembled microservice is shown in the right part of the figure below.
Non-functional dimensions
When we split according to the functional dimension, it is not all right. In most scenarios, we also need to add other dimensions to further split, in order to finally solve the problems caused by the monolithic architecture.
- Extensibility : Distinguish the changed and unchanging parts of the system. The unchanging parts are generally mature and general service functions. The changed parts are generally functions that have more changes and meet the needs of business iteration scalability. We can The unchanging part is split out as a shared service, and the changed part is separated out to meet the needs of personalized expansion. At the same time, according to the 28th principle, the frequently changing part of the system only accounts for about 20%, while the remaining 80% is basically unchanged or very little changed. This split also solves the problem of excessive release frequency that affects the stability of mature services. problem.
- Reusability : There are often repeated functions in different businesses or services. For example, each service has functions such as authentication, current limiting, security, and log monitoring. These passed functions can be separated to form independent The service, which is the API gateway in the microservice. For example, for Didi’s business, there are express and Shunfeng businesses, both of which involve the function of order payment, so the order payment can be separated and used as a general service to serve the upper-level business. As shown below:
- High-performance : Split modules with high performance requirements or high performance pressures to prevent services with high performance pressures from affecting other services. Common splitting methods are related to specific performance bottlenecks, such as e-commerce panic buying. The most important performance pressure is the queuing function of the entrance, which can be independent of the queuing function as a service. At the same time, we can also split based on read-write separation, such as e-commerce product information. On the App side, there are a large number of read operations on the business details, but the number of visits to the merchant center on the write side is very small. Therefore, it is possible to separate the read and write of the services with larger traffic or more core, split into two service releases, one is responsible for reading, and the other is responsible for writing. And data consistency is another point that needs to be considered when splitting based on the performance dimension. For strongly consistent data, it is strongly coupled and should be placed in the same service as much as possible (but sometimes it is necessary to split for various reasons, then Need to have a responsive mechanism to ensure), weak consistency can usually be split into different services.
- High availability : Separate core services with high reliability requirements and non-core services with low reliability requirements, and then focus on ensuring the high availability of core services. During the specific split, there 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, a core service can be split into a non-core service. The core service can be accessed by the transaction service, and the non-core service can be accessed by the merchant center.
- Security : Different services may have different requirements for information security. Therefore, services that require high security are separated and deployed separately. For example, setting a specific DMZ area to deploy services by partition can be more targeted Satisfying the requirements of information security can also reduce the throughput and concurrency requirements of security devices such as firewalls, reduce costs, and improve efficiency.
- Heterogeneity : For business scenarios that require development language types, different languages can be used to separate their functions to achieve an independent service.
above several splitting methods are not more than one choice, but can be freely arranged and combined according to the actual situation. At the same time, the split is not only an adjustment of the structure, but also means that the corresponding adaptive optimization of the organizational structure must be made to ensure that the services after the split are maintained by a relatively independent team.
Why are the services split up?
The ancient Greek philosopher Heraclitus once said: "One cannot step into the same river twice." With the passage of time, the state of everything will change. The same is true for online systems. Even a system will never be exactly the same at different times. The service granularity that is now split may be appropriate, but who can guarantee that this granularity will always be correct.
Services are dismantled, why are they still combined? It is to constantly adapt to the new business development stage. I will make an analogy here to see if you are clear. Dismantling is equivalent to our code development, and combining is equivalent to refactoring the code. Why refactor? I believe You know for sure. The same is true for the integration of microservices. As we learn more about the application domain, they may change over time. For example, you may find that a particular decomposition is inefficient due to excessive inter-process communication, and you have to group some services together.
At the same time, the increase in maintenance costs caused by the mismatch in the number of personnel and services is also an important reason for the consolidation of services. For example, the impact of this year's epidemic has caused many companies to lay off a large number of employees, and the number of services has not changed. This has caused an imbalance in the number of services and personnel. A developer has to maintain at least 5 service developments at the same time, and efficiency has dropped significantly.
Then if the number of microservices is too large and the resources do not match, you can consider merging multiple microservices into a service package and deploying to a server, which can save basic resource consumption during service operation and reduce maintenance costs. It should be noted that although the service pack runs in a process, the services in the service pack still have to meet the microservice definition, so that they can be separated quickly when they are to be reopened someday in the future. The schematic diagram of service merging into service package is as follows:
Risks to be aware of during the split
1. Don't fight unprepared battles
Whether the development team has sufficient experience and whether it can control the technology stack of microservices may be the first point to consider. It is not that the team must have perfect experience to start the service split. It is the best if the team has experts in this area. If not, it may be necessary to conduct sufficient technical demonstrations and rehearsals in advance, at least not to fight unprepared battles. To avoid dismantling whichever is simple, and which new business is going to be launched, start with a service first. Otherwise, there may be pitfalls on some common distributed problems, such as insufficient server resources, difficult operation and maintenance, call confusion between services, call retries, timeout mechanisms, distributed transactions, and so on.
2. Constantly correct
We need to admit that our knowledge is limited, and we can only work out a relatively suitable split plan based on the current business status and limited future predictions, rather than the so-called optimal plan. Any plan can only guarantee Provides a relatively suitable granularity and division principle at the moment, and we must always be prepared to become untimely and need to be adjusted again at the last moment in the future. Therefore, as the business evolves, we need to re-examine whether the division of services is reasonable. For example, if the service is too finely divided, the efficiency of personnel will decrease, and the probability of failure will greatly increase. Therefore, we need to re-divide the domain boundaries.
3. Be an activist, not a theoretical one
In terms of how to split it, don't worry too much about whether it is appropriate. How can you know whether it is appropriate without doing it? If after dismantling it is found to be really inappropriate, just readjust it. You might say that the cost of rebalancing is relatively high. But in fact, the essence of this question is whether there is a complete capability system for the service-oriented architecture, such as service governance platform, data migration tools, data double writing, etc. If so, the cost of re-adjustment will not be Too high.
Copyright Notice: content of this article is contributed spontaneously by Alibaba Cloud real-name registered users, and the copyright belongs to the original author. The Alibaba Cloud Developer Community does not own its copyright and does not assume corresponding legal responsibilities. For specific rules, please refer to the "Alibaba Cloud Developer Community User Service Agreement" and the "Alibaba Cloud Developer Community Intellectual Property Protection Guidelines". If you find suspected plagiarism in this community, fill in the infringement complaint form to report it. Once verified, the community will immediately delete the suspected infringing content.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。