Effectively communicate between Microservices
Choose between http/1.1 and gRPC. TL; DR: Use gRPC
How microservices communicate with each other can affect performance and scalability of the application. Communication between services can be synchronous or asynchronous. For this blog post, we will focus on synchronous. We have 2 common protocols at our disposal
- HTTP/1.1: The “default” http call
- gRPC: High performance remote procedure call (RPC framework). gRPC.io has a comprehensive documentation and how it works.
Let’s look at some sample code and run some performance test to pick our choices.
Non-cluster mode
Let’s start small and try to get one microservice talk to another one.
Our application has following components
- Load Testing tool: jMeter
- Service A: Makes a request to serviceB and returns that response.
- Service B: Replies with a static JSON after 10ms of delay for all the APIs
- VMs: Both the VMs are Amazon EC2 t2.xlarge machines
HTTP/1.1
This is the default request we make when we use any of the HTTP client libraries like axios, superagent.
Let’s create ServiceB
to implement our APIs.
Next, we create ServiceA
which calls ServiceB
with HTTP/1.1
With these two services running, we can now fire-up our jMeter
to run some performance test. We will use 50 users will 2000 request each. As we can see in the screenshot below, our median is 37ms
.
gRPC
gRPC uses protocol buffers by default. In addition to serviceA
and serviceB
, we also need a proto
file which will define our remote calls.
Let’s implement serviceB
again, this time using gRPC
Few things to note:
- We create
grpc
server atline 4
- We add a service to our server at
line 16
- We bind
port
andcredentials
at line 23
serviceA
implementation using gRPC is below
Few things to note:
- We create
grpc
client atline 4
- We make a remote call at
line 6
Let’s run our jMeter tool test again.
As we can see from this data, gRPC
is 27% faster than the normal HTTP/1.1 request
Application architecture in cluster mode
If you are running anything in production, it is most likely you are running many instances of any given service. In this case, we are making the following changes:
- Running three instances of our service on different ports
- We are using NGINX as a load balancer
HTTP/1.1
No changes are required on the services side. All we need to do it configure our nginx
to load balance the traffic with serviceB
. We can modify the /etc/nginx/sites-available/default
to look like this
We can now start our 3 instances of serviceB
and run our performance test
gRPC
Support for gRPC was recently added to nginx version 1..13.10 . So, we need to get the latest one as the default sudo apt-get install nginx
will not work.
We are not using node in cluster mode as gRPC is not supported.
Follow the steps below to get the latest nginx
We would also need the ssl certificates. We can create self-signed certificate using openSSL
Next, we need to change our /etc/nginx/sites-available/default
file to start using gRPC
.
That’s it. Let’s run our performance test again
As we can see gRPC
are 31% faster in comparison to the HTTP/1.1
Conclusion
gRPC is fast. In the tests above, we have 31% gain over HTTP/1.1 by just changing on how we talk to each other.
The full source code can be found on GitHub