gRPC — An Introduction Guide

Vinoth Selvaraj
6 min readFeb 18, 2021

Microservices are the popular way to design distributed systems. A big monolith application is broken down into multiple independent Microservices. These Microservices have advantages compared to traditional monolith applications — like easy to deploy, scale, reuse etc.

However Microservices do not come alone. There will be always more than 1 service. These Microservices communicate with each other mostly with REST using HTTP/1.1 protocol by exchanging JSON.

For example: If an user tries to send a request to order-service to order a product, order-service might internally send multiple requests to other services to fulfill the request. One request from user might trigger multiple internal requests among microservices in an application design.

REST is simple, very easy to use & great browser support. Easy to test our APIs. Developers love this. So we always use REST for our inter-microservices communication. However it has following issues.

  • HTTP/1.1 is textual & Heavy. Microservices exchange information by using huge JSON payload.
  • HTTP is stateless. So additional information is sent via headers which are not compressed.
  • HTTP/1.1 is unary — that is — you send a request and get a response. You can not send another request until you receive the response.
  • HTTP request requires a 3 way message exchange to set up a TCP connection first which is time consuming.

This all can affect the overall performance of our Microservices. REST is good between browser and back-end. But we need something better than REST for inter microservices communication to avoid above mentioned issues.

RPC:

RPC, Remote Procedure Call, is an old mechanism in distributed computing, to execute certain procedure in a remote machine without having to understand the network details. Processes in the same system/different systems which are not sharing the same address space can use RPC for their communication. The call will be made as we would normally invoke a local method call. It follows the client-server model. A client sends a request to the server by invoking a method on the remote server and exchanges messages. RPC provides a well defined interface and type safety.

gRPC:

gRPC is a RPC implementation / framework from Google for inter-microservices communication. Google has been using this for more than 15 years (internal name is Stubby). It is battle tested for more than a decade. Google site shows they have been processing 10 BILLIONS requests / second using gRPC.

gRPC is faster than REST (Checkout this gRPC vs REST Performance Comparison). We achieve this performance gain by switching to gRPC because of these 2 important reasons along with other in-built tools.

gRPC by default uses HTTP/2 for transport and Protocol Buffers for message exchange instead of JSON whereas most of the current microservices architectural style is REST with JSON on top of HTTP/1.1

HTTP/1.1 vs HTTP/2

Protocol Buffers vs JSON

By combining the above HTTP/2 and Protocol Buffers, gRPC becomes a better choice for inter-microservices communication.

REST vs gRPC

gRPC Course:

By the way, I learnt gRPC + Protobuf in a hard way. But you can learn them quickly on Udemy. Yes, I have created a separate step by step course on Protobuf + gRPC along with Spring Boot integration for the next generation Microservice development. Click here for the special link with discount.

gRPC API Types:

REST by default is unary. We send a request and get the response. But gRPC supports streaming requests and responses along with unary APIs.

  • Unary: This is a regular blocking request and response call.
  • Client Streaming: Client keeps on sending a request to the server by using a single TCP connection. The server might accept all the messages and sends a single response back. Use case: File upload functionality
  • Server Streaming: Server sends multiple messages to the client via single TCP connection. Use case: Pagination or Server pushes periodic updates to the client asynchronously.
  • Bi-Directional Streaming: Client and Server can keep on sharing messages via single TCP connection. Use case: Chat application or GPS or Client & server have to work together in an interactive way to complete a task

Service Definition:

Lets assume that we need to a develop a Calculator application which provides the following functionalities.

  • Unary: Finding factorial for the given number
  • Client Streaming: Client sends multiple numbers and the server has to sum them all
  • Server Streaming: Client sends a number to the server for which Server has to find all the factors. For example, If the client sends 6, the server will respond with 2 and 3.
  • Bi-Directional Streaming: Client sends multiple numbers to the server. Server has to check them one by one. If the number is prime, server will pass it back to the client.

We know the functionalities to be implemented on the server side. We also know what to expect from the client and what to respond back. Lets come up with a service contract using Protocol buffers as shown below.

syntax = "proto3";

package calculator;

option java_package = "com.vinsguru.calculator";
option java_multiple_files = true;

message Input {
int32 number = 1;
}

message Output {
int64 result = 1;
}

service CalculatorService {
// unary
rpc findFactorial(Input) returns (Output) {};
// server stream
rpc getAllFactors(Input) returns (stream Output) {};
// client stream
rpc sumAll(stream Input) returns (Output) {};
// bi-directional stream
rpc findPrime(stream Input) returns (stream Output) {};
}

The above service definition is platform neutral and language neutral.

gRPC — Project Set up:

  • Create a maven project with following dependencies.
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.30.2</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.30.2</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.30.2</version>
</dependency>
  • The above service definition file is placed in the src/main/proto path
  • Running below command will automatically create all the classes with abstract methods for us to implement the server side functionalities.
mvn clean compile
  • Lets assume that our client implementation is going to be in JavaScript. Protocol Buffers can also generate the client library automatically by using the same service definition in JavaScript to send the requests to the Java back-end server and receive the response.

Summary:

In this tutorial, we discussed the need for gRPC, API types, project set up etc. Lets further explore how to implement the Microservice/Client-Server application using gRPC and make use of its various RPC types as part of below articles.

  1. gRPC Unary API In Java — Easy Steps
  2. gRPC Server Streaming API In Java
  3. gRPC Client Streaming API In Java
  4. gRPC Bidirectional Streaming API In Java

The source code is available here.

Happy learning :)

--

--

Vinoth Selvaraj

Principal Software Engineer — passionate about software architectural design, microservices.