Microservices Architecture

background

The core of a traditional WEB application is divided into business logic, adapters, and an API or WEB interface accessed through a UI. Business logic defines business processes, business rules, and domain entities. Adapters include database access components, message components, access interfaces, and so on.

Usually, all modules are packaged in the same program and deployed on the server. For example, for Java applications, they can be packaged into JARS or wars and deployed in Tomcat containers. This traditional approach is suitable for small businesses, with fast development, code concentration, easy debugging, convenient deployment, and no network loss between different modules.

But for big Internet companies today, that traditional approach no longer works:

  • Low development efficiency: a large amount of development is concentrated in the same code repository, which requires frequent code merging when submitting and synchronizing codes;
  • Code maintenance is difficult: the code function is coupled together, it is difficult for newcomers to maintain the old code;
  • Inflexible deployment: a small change requires the entire system code to be recompiled and deployed;
  • Stability in doubt: a bug in one module can kill the entire system (e.g. C++ segment errors kill the entire process;
  • Insufficient scalability: If the volume of service exceeds the capacity of the single machine, there is no good way to improve the server performance.

The basic pattern

Micro service concept applied to the design of the business functions, applications will be able to start with in the design of business function or process design first break up, every business functions will be independent implementation into an individual services can run independently, and then reuse the same agreement will all applications require service together, form an application. If the need for a specific business function to expand, as long as the service for the business function to expand, don’t need the whole application extension, at the same time, due to the micro service is based on the realization of the business function orientation, so as not to interference by application, micro service administrators can view of operational resources need to configure the service to different computing resources, Or build new computing resources and deploy them.

Several problem points

There are some differences between microservices and traditional design, thus introducing new problem points.

The database

The first problem microservices face is the problem of database design. There are usually three practical ways:

  • Each service has a database, and services with the same attributes can share the same database.
  • All services share the same database, but different tables, and are not accessed across domains.
  • Each service has its own database, even for services with the same attributes, and the database is not shared.

However, it is worth noting that, in order to realize the independent operation of each module of the micro-service, the database here does not only store the data needed by the service, but refers to all the data needed by the service, so as to reduce the dependency between the services.

What would be the downside if one database served all microservices?

  • Single point of failure: When the database goes down and all services that depend on the database die, decoupling of microservices makes no sense at all.
  • Transaction management: When more services share the same database, locking waits occur more frequently, resulting in reduced actual usage performance.
  • Poor scalability: When a service needs to be expanded, the optimization and expansion of the required table may affect other microservices.

Sharing Session

For example, we divide a blog system into the following modules: user management, blog management, comment module, if the user logs in one module, how to make other modules also get the user login status?

Scheme 1: Session sharing

Session in each micro-service is put into Redis, and session sharing is realized by reading RedIS. For the scenario of obtaining login information, the specific steps are as follows:

  1. The user requests the gateway, and the gateway forwards the request to the login service for user name and password verification. After verification, the sessionId and user ID are associated and stored in Redis, and the page requested before login is returned.
  2. When invoking other micro-services, the gateway service obtains the user ID associated with the sessionId from Redis. If the user ID exists, the user is logged in, and the user is allowed to invoke. Otherwise, the user is redirected to the login page.

Because each microservice stores the session in Redis, the session is shared globally. The benefit of this is simple implementation, because Spring Session already integrates redis, it is easy to save sessions to Redis, and single sign-on/logout effect can be achieved, ** but from the perspective of microservices, it will increase the system coupling degree. ** In practice, a single Redis server or cluster can be used for session sharing.

Scheme 2: IP hash mode

In this way, for microservice cluster, the same microservice module may have many same machines as a cluster to provide services externally, so the machines may be different each time through the load balancing server, so how to maintain the previous Session?

A straightforward and crude solution would be to have the load balancer use a hash algorithm that assigns the same IP address to the same machine at a time, thus achieving the same session. (This method is not good.)

Solution 3: Token mode

In this way, the server does not store the Session, and each time the client accesses it, a token is attached, and the server restores the client information from the token. At present, JWT token is the mainstream method.

JWT means that the server generates a JSON object to the user after authentication. When the user communicates with the server in the future, the user will attach this JSON object and the server will restore the user information. JSON, as a plaintext object, is carried with each transfer, which is very insecure, so the server adds a few fields to generate the JWT and encrypts it with signatures.

Therefore, the server does not need to store the Session, and different microservice components can restore data from the Token, thus ensuring that the data accessed by each component is consistent.

Message communication message queue

The application scenarios of message queues are as follows:

  1. Asynchronous processing, such as SMS sending and email verification processing required for user registration;
  2. Application of decoupling, such as order system and inventory system decoupling;
  3. Traffic peak elimination, for example, queuing when the user traffic is too heavy.

Message queues mean that you can broadcast A “create new user” event on the A service, which can incidentally have data for the new user. The B service can listen for this event and handle it once it is received. These processes are asynchronous, which means that service A does not need to wait for service B to finish processing the event to continue, which means that service A cannot get the result of service B’s processing.

Remote RPC call

In real projects, complete decoupling of all microservice components is difficult to achieve, and sometimes it is difficult for service A to call the results of service B’s services. There is also A way to do this by having service B provide an HTTP RESTful interface that service A calls each time.

Remote Produce Call (RPC) is a technical concept. RPC framework enables developers to write HTTP requests without manual writing, and the specific code implementation is encapsulated in the framework, such as Dubbo. The core of RPC is not the protocol used. The purpose of RPC is to let you call a remote method locally, but the call is transparent to you and you don’t know where the method is deployed.

With RPC, services can be decoupled, and you only need to invoke the service, regardless of who implements the service or where it is deployed. There are two types of RPC calls:

  1. The synchronous call client waits for the call to complete and returns the result.
  2. An asynchronous invocation client does not have to wait for the execution result to return after the invocation, but can still get the return result through callback notification. If the client does not care about the return of the call, it becomes a one-way asynchronous call, and the one-way call does not return the result. The difference between asynchrony and synchronization is waiting for the server to complete and return the result.

Service Exploration Consul

RPC allows different microservice components to communicate with each other, but knowing which microservice component to communicate with requires service exploration capabilities, commonly known as Consul framework.

When an individual microservice goes live, it registers its IP location and service content with Consul, so it does not have to show its IP location to each microservice and therefore does not have to be set up individually for each microservice. When a service needs to call another service, it will ask the service discovery center for the IP location of the service. After obtaining the location, it can directly call the target service.

The idea is to centralize the location of all services so that they are not scattered across each microservice, and the Service Discovery Center can perform health checks on microservices at regular intervals (e.g., through: TCP call, HTTP call, Ping), if the service does not respond within a period of time, it is removed from the service center to prevent other microservices from calling a service that does not respond.

Now that you’ve seen it, give it a thumbs up before you go!

Refer to the link

  1. SpringCloud Microservices Session consistency solution
  2. wikipaedia
  3. JWT
  4. Introduction to Service discovery and simple use of Consul framework