avatarDineshchandgr - A Top writer in Technology

Summary

The provided content discusses the foundational aspects of synchronous communication in microservices architecture, detailing the protocols used, such as REST, gRPC, and GraphQL, and outlining key considerations for designing robust synchronous communication systems.

Abstract

The article "Microservices Communication part 1-every programmer must know" delves into the critical role of synchronous communication in microservices architectures. It emphasizes that there are only three primary methods of communication between services: synchronous, asynchronous, and hybrid. The focus of this part of the article is on synchronous communication, which is characterized by direct service-to-service interaction using an HTTP request-response model. The author explores various protocols suitable for this type of communication, including REST API, gRPC, and GraphQL, each with its own advantages and use cases. The article also highlights the importance of non-blocking IO, load balancing, circuit breaker patterns, caching, and distributed tracing in the design of microservices to ensure system resilience, efficiency, and maintainability. The author plans to cover asynchronous and hybrid communication methods in a subsequent article.

Opinions

  • The author suggests that understanding microservices communication is essential for any programmer working with distributed systems.
  • The preference for HTTP/2 over HTTP/1 is expressed due to its benefits in performance and efficiency.
  • The use of gRPC is recommended for applications requiring low latency and high throughput, despite the complexity in debugging due to its use of binary Protobuf files.
  • GraphQL is presented as an effective solution for aggregating data from multiple microservices into a unified API, which can reduce bandwidth usage at the cost of some latency.
  • The author advocates for the adoption of non-blocking IO libraries, such as Spring WebClient, to optimize resource usage.
  • Client-side and server-side load balancing are both discussed as viable strategies, with Ribbon in Spring Boot being highlighted for client-side load balancing.
  • The Circuit Breaker pattern is strongly endorsed to prevent cascading failures and allow for recovery of failing services.
  • Caching is proposed as a method to reduce the load on services and decrease latency for frequent read operations.
  • The importance of distributed tracing is underscored to facilitate the understanding of request flows and to aid in the construction of resilient microservices architectures.

Microservices Communication part 1-every programmer must know

Image Source: http://static1.squarespace.com/static/588a02f11b10e3d4643f5c35/588a2427cd0f68457c5c4b00/61f02aa30472837195a9ae28/1673540882083/Microservices%2BCommonication%2BFrameworks_Synchonous_Asynchronous_EQengineered.png?format=1500w

Hello Everyone. Microservices communication is the heartbeat of any microservices architecture and designing them could make or break the system. There are just 3 ways of communication between the services i.e synchronous, asynchronous, and hybrid. There is a lot of confusion around this and hence I decided to write an in-depth article on this topic. However, the article went quite long and I decided to split it up into 2 parts. In the first part of this article, we will see the Synchronous Communication between microservices and we discuss different protocols like REST, gRPC, and GraphQL. Then we will see the important aspects to be considered when designing the synchronous communication between microservices. Let's get started.

Before we start this article if you want to understand in-depth on microservices and their design patterns, please go through my article below

What is Microservices Communication?

During Monolith days, communication means connecting our application with external systems like payment gateways. Ever since the microservices architecture evolved, the services got distributed and communication between them forms the heartbeat of the whole architecture. To add to the complexity, every microservice has multiple instances running, and making them talk to the right instance of the right service to get the job done is the most important aspect of any microservices architecture. Let us look at the various ways of communication between the microservices, the important aspects in the following section.

Types of Microservices Communication

This is one of the confusing aspects when we talk about microservices communication but it's quite easy. There are only 3 ways the microservices can communicate as follows

  1. Synchronous Communication
  2. Asynchronous Communication
  3. Hybrid Communication

In this article, we will only look at Synchronous communication. In the next part of the article, we will see about Asynchronous and Hybrid communication between the microservices.

1. Synchronous Communication between Microservices

In synchronous communication, microservices call each other directly to their IP address and this works on an HTTP request-response model using REST API. Microservice 1 either gets the static IP of the Microservice upfront or gets the dynamic IP address (usually private IP) from the service registry like Eureka where all the instances register themselves. If Microservice 2 is down, Microservice 1 will get an error and then the action cannot be performed and the message is lost. We cannot do a retry mechanism in this direct communication.

a. REST API with HTTP/2

The synchronous communication happens over HTTP/1 or HTTP/2 using protocols like REST, gRPC, and GraphQL. HTTP/1 is very slow and it adds some latency hence it is better to use the HTTP/2 to get the benefit of multiplexing (less bandwidth and more efficiency). Usually, all the microservices run inside the private subnet which means they do not have a public IP and cannot be reached directly from the web. Hence we usually use HTTP instead of HTTP(s) for communication inside the cluster.

However, to use HTTP/2 it is mandatory to use it over HTTP(s). In order to use HTTP(s), we need to generate a self-signed SSL certificate and load it to the microservice instances. Then we can easily make REST API calls using HTTP/2 instead of HTTP/1 calls which makes the communication very effective.

You can read my below article to understand in detail about HTTP/2

b. gRPC Protocol

Let's say you have a lot of API calls happening in the system and your application is of an e-commerce or finance nature, then you might need to use gRPC protocol. gRPC is designed for low latency and high throughput communication and it is great for lightweight microservices where latency is critical. gRPC has excellent support for bi-directional streaming and it uses two powerful things under the hood i.e HTTP/2 and Protobuf.

You can take a look at my article on gRPC where I explained in detail

The only problem in gRPC is that debugging gets complicated as we use the binary files called Protobuf. Using a normal HTTP/1 or HTTP/2 REST calls, debugging is easy as we use JSON format in general. But if you weigh the pros and cons, then gRPC should be the ideal choice for the microservices that communicate quite often and needs a low latency.

c. GraphQL Protocol

Another important protocol used in synchronous microservices communication is GraphQL. This also works on top of HTTP but in a different aspect.

Image Source: https://i.stack.imgur.com/BrnFy.png

GraphQL is the perfect technology to bring your microservices together for aggregating the data as a unified API. We use GraphQL as a data layer for the microservices and combine the data from all these services into a single API that responds to the client. This is synchronous as the GraphQL Server/gateway needs to wait for the response from the other microservices but it aggregates all the data into a single response to the client. This means the client just makes a single API call to get the data it needs without making multiple round trips. This saves a lot of bandwidth at a cost of little latency.

You can check out my article on GraphQL below

Important Aspects of Synchronous Communication in Microservices

Having seen in detail different protocols for synchronous communication, let us look at the important aspects to be followed.

1. Non-Blocking IO

When microservice 1 calls microservice 2, an HTTP Request is made and microservice 1 waits for the HTTP Response. The thread will keep waiting until the response is received and it uses up the system resource. Imagine there are around 100 API calls at the same time from service 1 to 2, then service 1 is gonna be down soon. An example of this is the RestTemplate library in SpringBoot which is synchronous and blocking.

In most programming languages these days we have non-blocking IO libraries available. One such library is the Spring WebClient. It is still synchronous but it will not block the thread until the response is received. Instead, the thread does another job and a notification is received once the response is ready from Microservice 2.

In some use cases, the non-blocking approach uses much fewer system resources compared to the blocking one. So you can consider using a nonblocking IO library depending on the language you use.

2. Load Balancing

Earlier, we discussed each microservices running multiple instances when its scales up on the load. In such cases, it is very very important for us to send the requests in a load-balanced manner to each of the instances. Failing to do so will result in a single instance of a microservice bombarded and hinder the whole system.

There are two ways we can use a load balancer when we call another microservice.

a. Client Side Load Balancing

In a Client Side load balancing, the Catalog Service requests the details of the Product Service from the Service registry and obtains the IP of all the 3 instances. Every Microservice instance has a Client Side load balancer running inside which decides which instance of Product Service to call. Eg: We have a library called Ribbon in Spring Boot. This does the work of Client Side load balancing.

b. Server Side Load Balancing

In Server Side load balancing, we use the domain name of the load balancer that we define for the product service. Under this domain, there are three instances of Product Services registered now. So when Catalog Service calls the Product Service domain name, the load balancer uses its algorithm to route the requests to each of the instances. A good example of such a load balancer is AWS ELB or Nginx etc.

3. Circuit Breaker

Another important aspect of synchronous communication is the Circuit Breaker. Circuit Breaker pattern can allow a microservice to continue operating when a related service fails, preventing the failure from cascading and giving the failing service time to recover. If microservice B is down, the circuit is open and there won't be any calls made from Service A to B. Then service A will check for service B and closes the circuit once service B is up.

Image Source: https://media.licdn.com/dms/image/C4D12AQEr5SZ8jEAoEw/article-cover_image-shrink_423_752/0/1521338367853?e=1683763200&v=beta&t=pB9yysvKM0EpWo3PM8FASZchPCH6DRauT2s04elcmQ0

You can read about Circuit Breaker in detail in my article

4. Caching

When two services communicate with each other frequently for read operations i.e GET request, we can consider using a Cache rather than calling Microservice 2 every time. This will reduce the load on Service 2 and also reduce the latency of the request as the Cache is blazing fast as it runs on the RAM memory of the machine. There are 2 options to consider in-memory caching or distributed caching.

5. Distributed Tracing

When we have a chain of synchronous communication happening in microservices, it is very important for us to trace the requests to understand where they fail or which service takes a long time to process. Understanding this will help us to build resilient microservices architecture and we need to use the pattern called Distributed Tracing

Please read more on this in my article below,

Summary

In the first part of the Microservices Communication article, we saw about 3 ways of communication between the services i.e Synchronous, Asynchronous, and Hybrid. We dived deep into the Synchronous Communication between microservices and we discussed using different protocols like REST, gRPC, and GraphQL. Then we have seen the important aspects to be considered when designing the synchronous communication between microservices.

Hope you liked this article and thanks for reading this!!!

In the next part of the article, I will walk you all through the Asynchronous and Hybrid communication between microservices and also discuss their advantages and drawbacks.

If you like to get more updates from me, 
please follow me on Medium and subscribe to the email alerts.

If you are considering buying a medium membership, 
please buy through my referral link

List of Related Articles

Technology
Programming
Software Engineering
Artificial Intelligence
Data Science
Recommended from ReadMedium