The microservice architecture allows you to divide the service into separate functions, independently scale individual parts, provide increased fault tolerance, use different technologies for different tasks, and more. But the transition from a monolithic architecture to a microservice one is a complex process, the most difficult step of which is changing the mechanism for the interaction of internal components. We understand what are the difficulties of the transition and how the interaction is arranged in the architecture of microservices.
Monolith vs microservice
Microservice architecture appeared at a time when it became difficult and inconvenient to work with “monoliths”. With the new principle of building applications, microservices received a completely a different principle of component interaction – in a monolithic architecture, in-process interactions are used, and in a microservice, the interaction of modules occur through a network using a protocol-independent technology.
In addition, in monoliths, components refer to each other at the code or function level and are executed within the same process. Directly changing in-process calls to remote procedure calls to services will not provide the interaction that would suit distributed environments.
How to deal with the situation
There is no unified solution that allows you to ensure the correct interaction when switching to microservices – each situation needs its own. One of these is the isolation of business-relevant microservices. When implementing such a solution, internal microservices will interact asynchronously and in less detail. In this case, calls will be grouped, data from several services will be aggregated and only then sent to the client. The second option is to create an architecture in which individual microservices will be partially dependent, but as consistent as possible. It should be noted that each microservice must have its own data and logic.
Communication types
The interaction between the client and the service can be implemented using different types of links. They can be divided into two groups.
First group
Sets the protocol type – asynchronous or synchronous.
Asynchronous protocol. The client code or message senders do not wait for a response – messages are sent in the same way as passing to the queue of any broker. This type uses the AMQP protocol.
Synchronous protocol. When sending a request, the client waits for a response from the service – tasks are executed only after the server sends a response. An example of such a protocol is HTTP.
Second group
Sets how many recipients the request has.
One recipient. Each request is handled by a specific recipient or service.
Multiple recipients. For each request, the number of recipients is different. Interaction is built using asynchronous protocols.
Microservice applications often use a combination of the two styles. For example, for interaction with one recipient – synchronous protocol, and for asynchronous – message protocols. But when creating microservices, it is not the type of communication that matters more, but the ability to asynchronously integrate microservices without reducing their independence.
Asynchronous integration as a way to ensure the autonomy of microservices
When creating applications with a microservice architecture, it is important to correctly implement the integration method – ideally, so that internal microservices interact with each other minimally, and the interaction is asynchronous.
It should be understood that using synchronous communication between multiple microservices is not the best option – each microservice must be autonomous and available to the client, even if other services are disabled or unavailable. If this is not implemented, the architecture will be fault-tolerant – if one service is unavailable, the entire application will be unavailable.
In addition, the presence of HTTP dependencies between microservices affects not only their autonomy, but also their performance – the fewer synchronous dependencies, the higher the response speed in the client application.
The advantage of the asynchronous type of communication is that the client’s request is processed immediately, while with the synchronous model, all processing is performed simultaneously. Therefore, it is better not to use the synchronous method of interaction within the framework of the original request-response operation.
The asynchronous type of communication can be used even if the original microservice needs data from another microservice. In such a situation, you can refuse synchronous queries by making data replicas to the database – this is acceptable.
Based on this, the main thing to understand is that do not use synchronous dependencies between microservices.
Interaction styles
In microservices applications, you can use different styles of internal interaction between modules. For example:
- if the interaction is performed outside the Docker host or microservice cluster, then a synchronous request and response mechanism is better suited;
- if the interaction is within a Docker host or cluster, a combined communication format or message-based asynchronous communication (such as AMQP) will do.
In addition, you can use a non-standard combined method, but this option is only suitable for internal interaction on a node or cluster – it is better not to publish services with this format.
Request-response operation using HTTP and REST
With a request-response interaction, a client request goes to a service that processes it and returns a response. This type of interaction is the best option for requesting data from client applications, so it is more often used in microservice architecture.
One common architecture style for this type of interaction is REST. The approach is based on the HTTP protocol and allows you to work with HTTP commands. In addition, REST services are suitable for developing ASP.NET Core Web API services.
Push Notifications and HTTP
Communication Another method is real-time one-to-many asynchronous interaction with top-tier platforms.
With this kind of interaction, the server code is able to autonomously send available data to clients, rather than waiting for it to request them.
One of the popular tools for building such interaction for quickly transferring data from the server to clients is SignalR. In this case, the processing performed by the WebSockets protocol with many connected WebSockets on the client side (one client – one WebSockets). For example, this method is used in sports applications when it is necessary for all users to transmit data on score changes in a match.