Communication Patterns in Microservices
Anand Nair
Engineering @ Salesforce | GenAI for Developer Tools | Globee Awards Judge | Reviewer of Tech Books
Microservices is a pattern that has gained popularity in the last decade. There have been numerous articles/books/blogs/tutorials/videos/learning courses that describe it. In this article, I would like to go over the popular communication practices between the services that are followed in the industry.
At a high level, there are 2 main interaction styles that happen between microservices.
Synchronous Communication.
In this interaction style, two services will have a one-to-one communication between them, and the client service expects a timely response from the server service. This could be achieved by using REST or messaging.
REST is an interprocess mechanism that uses HTTP. The main concept in REST is that it contains a single or a collection of business objects represented as a resource. Using REST we can manipulate(POST, PUT, DELETE) or fetch (GET) the resource. When developing REST-based APIs it is important to understand the Richardson Maturity Model explained by Martin Fowler.
The main benefits of using the REST-based model are simple and familiar, it doesn’t require an intermediate broker which simplifies the architecture of the system. The main drawback of using a REST-based approach is that it doesn’t support the publish-subscribe model. This approach could have reduced availability since both client and the server service should be available during the exchange of requests and responses. In this approach, the clients must know the URLs of the server service instances. REST APIs should deal with network timeouts and circuit breaking patterns.
Message Broker could be used to have a synchronous based communication. This falls under asynchronous style communication to achieve synchronous interactions between the services. Frameworks like eventuate tram helps to achieve synchronous communication using message brokers in an asynchronous style. The following figure shows the communication between 2 services using a message broker.
As seen in the above figure, the client service (Service A) sends a request with messageId, return address, and the payload to a channel (channel 2) configured in the message broker. The service subscribes to this channel (channel 1) and receives the request. The request has information about the return channel where the response needs to be sent. The server service (Service B) processes the request and creates a response using which is send to the return channel (channel 2) with the same messageId in the request as a correlationId. The correlationId helps the client service to map its request and act accordingly.
In this approach even if the server service is down momentarily, it would get the request that was sent by the client and the client would get the response back. The client service can wait for the response from the service their by making it a blocking call. One of the major drawbacks of synchronous communication is that it introduces tight coupling between the services.
We should be using this if the scenario demands it.
Asynchronous Communication
In this interaction style, there can be two or more services that could be part of the communication. When there are only 2 services involved in this communication, it becomes a one-to-one communication and the client service sends a request to the server service which replies to the response asynchronously. It might longer than usual for the server service to send a response back to the client. In this kind of interaction, the client doesn’t wait for the response. This is very similar to the async style synchronous communication which we discussed above. The only difference here is that the client doesn’t make a blocking call thereby making the communication asynchronous.
The client could publish a message which could be consumed by 0 to more services.
This style of inter-service communication is achieved using message brokers. The popular message brokers include Kafka, Rabbitmq, ActiveMQ, AWS Kinesis. All of these support point-to-point and publish-subscribe channels. The major benefits of using broker-based messaging are loose coupling, message buffering, flexible communication style.
By loose coupling, the client service doesn’t need to know where the other service is hosted. The receiving service could be in the same network or could be in a whole different pod. This helps developers to develop scalable applications without thinking much about the dependencies.
Broker based messaging enables message buffering until the message gets processed by the service.
One of the major drawbacks associated with this single point of failure. The message broker should be highly available.
To conclude, both styles have their pros and cons. So when we design and architect various applications, it is always good to compare and contrast between all the available options out there and pick the style of communication suits the application. There is a possibility to have both interaction styles to solve different use cases in the same application.
Acknowledgment
I have borrowed concepts from the book “Microservices Pattern†by Chris Richardson
The same article can be found at https://medium.com/@anandnair/communication-patterns-in-microservices-2de316d213cd.
Engineer/Cinephile/Cricket Passionate/News hound
4 å¹´Good one, would like to see a post on detailed explanation of REST APIs