Guest post by Nikhil Mohan, Senior Technology Architect at Infosys

More than ever before, present day businesses want their IT systems to constantly evolve and be capable of responding positively to the changing goals and priorities. As they say, change is the only constant. In this context, microservices have become the proverbial  Holy Grail for solution architects to design and build modern software.  However, microservices are complex to design. The essence of microservices architecture is to build software as a set of autonomous business capabilities that collaborate non-invasively to realize the whole solution. In the solution definition phase, it is quite easy to overlook some of the design complexities that arise when dealing with distributed systems as highlighted in Fallacies of Distributed Computing

Inter-service communication is one of the most critical design elements in a microservices-based solution that needs careful consideration. RESTful API carrying data in JSON is widely adopted as the most common communication pattern for connecting microservices together. 

However, this approach is suboptimal in the following scenarios: 

∙ REST is resource-oriented. This can be a limiting factor while dealing with API flexibility. 

∙ JSON payloads are human-friendly, but they are bulky and not machine-friendly. Therefore, JSON payload parsing is compute-intensive. 

∙ Data transfer in HTTP 1.1 is text-based and involves no compression of request headers. This results in high bandwidth utilization. ∙ A new TCP connection is established for every request/ response cycle in HTTP 1.1. Network latency becomes significant especially for chatty interactions.

Enter gRPC! 

gRPC is an open source framework developed by Google and currently managed under the aegis of Cloud Native Computing Foundation (CNCF). gRPC does all the heavy lifting work for inter-service communication leaving developers with only the task of defining a contract for remote procedure calls in a language-neutral format. Moreover, gRPC is action-oriented, thereby helping developers to design flexible APIs. 

gRPC uses HTTP/2 under the hood. HTTP/2 helps gRPC to overcome  some of the limitations with REST over HTTP 1.1 

∙ HTTP/2 supports multiplexing of requests and responses. This reduces latency making inter-service interactions faster. ∙ HTTP/2 supports server streaming paving the way for applications to leverage new integration use cases. 

∙ HTTP/2 is based on binary data transfer making it highly bandwidth-efficient. 

∙ HTTP/2 does header compression, again helping network bandwidth utilization. 

Along with the gains through HTTP/2, gRPC also offers the following  benefits: 

∙ Language independent. Very ideal for a polyglot microservices  architecture 

∙ Supports streaming communication pattern 

∙ Easy to plug in features such as authentication, load balancing,  logging, and monitoring 

∙ Supports TLS by default 

gRPC makes use of a language-agnostic data serialization mechanism called protocol buffers to specify the contract for remote procedure calls. 

Key characteristics of protocol buffers are listed below:

∙ Tooling support in all key languages for generating client and server code aiding developer productivity. 

∙ Data is in binary format and hence very efficient for large data transfers. 

gRPC is an especially suitable integration technology for internal services that are not client-facing. Due to its strongly-typed, contract-first nature, gRPC works well for services that are co-developed.  Moreover, the tooling support for gRPC on the browser is in nascent stage as of now. Therefore, a natural design choice as of now might be to have the edge microservices publish REST API and the internal services use gRPC as the integration technology. 

Sample architecture 

gRPC supports four types of API

Unary – Analogous to traditional request/ response pattern Server streaming – Server sends a stream of messages to a single request from the client. 

Client streaming – Client sends a stream of messages in the request and the server responds with a single message. 

Bi directional streaming – Client sends a stream of messages and the server responds with a stream of messages.

Now, let us look at an example scenario where gRPC fits the bill as the integration choice for the solution. 

Movie Finder application using gRPC 

Suppose we have to design a movie finder application that provides personalized movie recommendations to its users. The application accepts the movie genre as input from the user and recommends a  movie. The domain model for this seemingly simple use case can be modeled as given below: 

Movie finder application diagram

Movie controller – An external service that publishes API for client/ UI  to interact with the application 

Movie store – Holds a repository of movie records. This can be thought of as something like omdb.org

User Preferences – Keeps track of user activities. For simplicity, we can assume that it keeps track of all the movies that the user has watched, wants to watch or does not want to watch.

Recommender – The component that holds all the logic for making a  movie recommendation. Since the focus is on gRPC, we will probably not worry about the intricacies of implementing a recommendation engine here! 

As all of these functions refer to distinct business capabilities, it makes sense to model each of these components as microservices.  The interactions involving Movie Controller with Movie Store, User Preferences, and Recommender are all internal to Movie Finder application. Hence, as explained above, gRPC emerges as a natural choice for integration technology. To make the design complete,  Movie Controller can publish REST endpoints for the external world to consume. 

To summarize, the contract for gRPC services for this example can be defined as below. As mentioned earlier, the flexibility offered by gRPC can be put to use to architect highly performant distributed systems. 

Table showing input, output and gRPC API type towards movie application

Wrapping it up 

Architects like to view modern systems as a collection of numerous cloud native components. Being cloud native is fundamental to the solution, irrespective of whether the target solution is planned for cloud or not. It is easier to manage a solution component to adhere to cloud native principles when its size is small. This thought process is driving architectures towards more and more micro and nano services. The degree of distribution proportionately increases the need for efficient and flexible integration schemes. Therefore, when you are sitting down to design your next CXO eye-catching solution,  you may want to give gRPC a serious thought!