Microservice-based software architecture pattern

The concept of micro services is not a new concept, many companies are already practicing, such as Amazon, Google, FaceBook, Alibaba. The purpose of the Microservices Architecture Pattern is to build large, complex, long-running applications as a set of cooperating services, each of which can be easily modified locally. The word Micro means that each service should be small enough. However, the small size here cannot be compared by the amount of code, but should be compared in terms of business logic - only those that conform to the SRP principle are called microservices.

 

Leaving aside the issue of size, readers, the first thing you should consider is how to solve the development and deployment problems encountered by the current technical team. It is in the process of solving these problems that the concept of the microservice architecture pattern is gradually summarized and refined.

 

What is the difference between microservices and SOA? Microservices can be regarded as SOA without ESB. ESB is the central bus in the SOA architecture, the design graph should be star-shaped, and the microservice is a decentralized distributed software architecture.

 

The following topics will be discussed next:

  1. Motivation for applying microservices, compared to traditional monolithic applications
  2. Advantages and disadvantages of microservices
  3. Key issues that may be encountered when applying microservice architecture design (internal service communication, distributed data management)

1. Monolith

 

In the early days of web application development, most web projects package all functional modules (service side) together and run them in a web container. Many enterprise Java applications are packaged as war packages. Programs written in other languages ​​(Ruby, Python or C++) have similar problems.

 

Suppose you are building an online store system: customers place orders, check lists and credit card limits, and ship goods to customers. Soon, your team will be able to construct the system shown in the figure below.

 

Fig1- the monolithic architecture

Such a system that deploys all functions to run in a web container is called a monolithic application. Monolithic applications have many advantages: IDEs are designed for developing a single application, easy to test - you can start a complete system locally, easy to deploy - directly packaged as a complete package and copied to a directory in the web container to run below.

 

However, the above benefits are conditional: the application is less complex. For large-scale and complex applications, monolithic applications will be particularly cumbersome: to modify one place, the entire application must be deployed (PS: advantages also become disadvantages in different scenarios); compilation time is too long; regression testing cycle Too long; development efficiency is reduced, etc. In addition, the monolithic application is not conducive to updating the technical framework, unless you are willing to rewrite the system completely (the cost is too high for your boss or not).

 

2. Application split

 

Detail what happens to a website when its business scales up? Not enough concurrency? OK, add web server. Database pressure too high? OK, buy a larger and more expensive database. Databases are too expensive? The data of a table is stored separately, commonly known as "sub-database sub-table". No problem with these, good job. However, the abstraction ability of foreigners is stronger than ours, see Figure 2 below.

 

Fig2 - the scale cube

 

This figure summarizes the expansion process of a system from three dimensions: (1) x-axis, horizontal replication, that is, adding multiple web servers after the load balancing server; (2) z-axis expansion, which is the expansion of the database, that is Sub-database and sub-table (sub-database is to put closely related tables on one database server, and sub-table is because there is too much data in one table, and the data of one table needs to be placed on different database servers through hash) ; (3) The y-axis extension is function decomposition, which divides modules of different functions into different services. Expanding in the direction of the y-axis, the giant application can be decomposed into a set of different services, such as order management center, customer information management center, commodity management center, and so on.

 

There are many ways to divide the system into different services: (1) By use case, for example, an online store system will divide a checkout UI service, which implements the use case of checkout; (2) By resources, for example, it can be divided into A catlog service to store product catalogs.

 

There are two principles to follow for service division: (1) each service should conform to the single responsibility principle as much as possible - the Single Responsible Principle, that is, each service only does one thing and does it well; (2) reference The design of the Unix command line tools, Unix provides a large number of simple and easy-to-use tools, such as grep, cat and find. Every tool is small and beautiful.

 

Finally, it should be emphasized that the goal of system decomposition is not just to come up with a bunch of small services, this is not the goal; the real goal is to solve the problems encountered by monolithic applications when the business grows rapidly.

 

For the above example, after being divided according to functions and resources, the architecture diagram shown in Figure 3 below is formed. The decomposed microservice architecture contains multiple front-end services and back-end services. Front-end services include Catalog UI (used for product search and browsing), Checkout UI (used to implement shopping cart and ordering operations); back-end services include some business logic modules, we will refactor each service module in the boulder application for a separate service. What's wrong with doing this?

 

Fig 3 - the microservice architecture

 

The advantages and disadvantages of microservice architecture

 

1. Advantages

  • Each service is cohesive enough and small enough, the code is easy to understand, and the development efficiency is improved
  • Services can be deployed independently, and the microservice architecture makes continuous deployment possible;
  • Each service can be independently extended by x and z, and each service can be deployed on suitable hardware servers according to its own needs;
  • It is easy to expand the development team, which can be developed for each service component;
  • Improve fault isolation (fault isolation), a memory leak of a service will not paralyze the entire system;
  • The system is not constrained to a certain technology stack for a long time.

2. Disadvantages

It is mentioned in "Myth of Man-Month": There is no silver bullet, which means that it is impossible to build a skyscraper with just a hammer. Design ideas and implementation tools must be selected according to business scenarios. Let's take a look at what we trade in in exchange for the benefits mentioned above?

 

  • Developers have to deal with the complexity of distributed systems; developers have to design communication mechanisms between services, and for user cases that require multiple backend services, it is very difficult to implement code without distributed transactions; multiple Direct automation testing of services is also quite challenging;
  • The complexity of service management, managing multiple instances of different services in the production environment means that the development team needs to coordinate globally (PS: Now the emergence of docker is suitable to solve this problem)
  • How to grasp the timing of applying microservice architecture? For startups whose business has not yet been clearly understood and their business data and processing capabilities have not yet begun to grow explosively, there is no need to consider the microservice architecture model. The most important thing at this time is rapid development, rapid deployment, and rapid trial and error.

Fourth, the key issues of microservice architecture

 

1. Communication Mechanism of Microservice Architecture

 

(1) Communication between client and server

 

Under the monolithic architecture, the client application (web or app) sends HTTP requests to the server; however, under the microservices architecture, the original monolithic server is replaced by a set of microservices. In this case, how does the client What about making a request?

 

As shown in Figure 4, the client can initiate a RESTful HTTP request to the micro service, but this happens: in order to complete a business logic, the client needs to initiate multiple HTTP requests, resulting in a decrease in the throughput of the system, and then In addition, the high latency of the wireless network will seriously affect the user experience of the client.

 

Fig4 - calling services directly

In order to solve this problem, a role is usually added in front of the server cluster: API gateway, which is responsible for connecting with the client and converting the client's request into a series of calls to internal services. Another advantage of this is that the service upgrade will not affect the client, just modify the API gateway. The system architecture diagram after adding API gateway is shown in Figure 5.

 

Fig5 - API gateway

(2) Communication between internal services

 

There are two communication methods between internal services: synchronous mechanism based on HTTP protocol (REST, RPC); asynchronous message processing mechanism based on message queue (AMQP-based message broker).

 

Dubbo is Alibaba's open-source distributed service framework, which is a synchronous call. When there are too many services in a system, a registry is needed to handle service discovery problems. For example, a configuration server such as ZooKeeper is used to manage the address of the service: the publisher of the service To send a request to ZooKeeper, record information such as its own service address and function name; the caller of the service needs to know the relevant information of the service, and the specific machine address can be queried in ZooKeeper. This synchronous calling mechanism is intuitive and simple enough, but there is no "subscription-push" mechanism.

 

The representative systems of AMQP-based are kafka, RabbitMQ, etc. This type of distributed message processing system decouples subscribers and consumers, and message producers do not need consumers to be online all the time; message producers only need to send messages to message brokers, so there is no need for a service discovery mechanism.

 

Both communication mechanisms have their own advantages and disadvantages, and practical systems often contain both communication mechanisms. For example, in distributed data management, it is necessary to use both synchronous HTTP mechanism and asynchronous message processing mechanism.

 

2. Distributed data management

 

(1) Processing read requests

 

The online store's customer account has a limit, and when a customer tries to place an order, the system has to determine if the total order amount exceeds his credit card limit. The credit card limit is managed by the CustomerService, and the order placing operation is the responsibility of the OrderService. Therefore, the Order Service needs to request data from the Customer Service through RPC calls; this method can ensure that the Order Service obtains an accurate limit each time. The single disadvantage is that one more RPC call is made. , and Customer Service must remain online.

 

Another processing method is to store a copy of the credit card limit on the OrderService side, so that there is no need to initiate an RPC request in real time, but a mechanism is needed to ensure that when the credit card limit owned by the Customer Service changes, it must be timely Update the copy stored on the Order Service side.

 

(2) Processing update requests

 

When a piece of data resides on multiple services, data consistency must be guaranteed.

 

  • Distributed transactions

Using distributed transactions is very intuitive, i.e. to update the credit card limit on the Customer Service, you must also update the replica on the other service, either all or none of these operations. Using distributed transactions can guarantee strong data consistency, but it will reduce the availability of the system - all related services must always be online; also, many modern technology stacks do not support transactions, such as REST, NoSQL databases, etc.

  • Event-driven asynchronous updates

When the credit card limit in Customer Service changes, it publishes an event to the "message broker (message broker)"; other services subscribed to this event update the data when prompted. The event flow is shown in Figure 6.

Fig 6 - replicating the credit limit using events

5. Refactoring boulder applications

 

In actual work, there are very few opportunities to participate in a brand new project, and almost all complex and large-scale applications with problems of one kind or another need to be dealt with. At this time, how to gradually refactor the system into a microservice architecture while maintaining the old services?

 

  • Don't make things worse, when new requirements come, if you can develop it independently as a service, you can develop it independently, and then write glue code directly for the old service and the new service - this process is not easy, but it is The first step in decomposing a mega service, as shown in Figure 7;

Fig-7 - extracting a service

  • Identify modules in monolithic applications that can be separated as separate services. Generally, modules suitable for separation have the following characteristics: two modules have conflicting resource requirements (one is CPU-intensive and the other is IO-intensive); authorization authentication Layers are also suitable for isolating a service by itself. Each time a service is separated, the corresponding glue code needs to be written to communicate with the remaining services. In this way, in the process of gradual evolution, the architecture update of the entire system is completed.

Regarding refactoring, there is an article that I recommend everyone to read - the stress of overturning and starting over. There is a lot to write about refactoring. I hope I can make rapid progress and write more summaries to share with you.

 

Summarize

 

Microservices are not a cure for all diseases, nor are they new technologies. The biggest thing I learned from this is the scale cube. It is easier to analyze and practice the construction of large-scale systems from this coordinate axis.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326375269&siteId=291194637