Techdozo
  • Microservices
    • All
    • GraphQL
    • gRPC
    • Spring Boot
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    Distributed transaction in microservices using Saga

    Distributed Transactions in Microservices: implementing Saga with Temporal

    Temporal Workflow Orchestration

    Workflow Orchestration with Temporal and Spring Boot

    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

  • Spring Boot
    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful API Gateway with gRPC

    RESTful API Gateway with gRPC

  • gRPC
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    gRPC Interceptor: unary interceptor with code example

    gRPC Interceptor: unary interceptor with code example

    gRPC: synchronous and asynchronous Server streaming RPC

    gRPC: synchronous and asynchronous Server streaming RPC

    Photo by Ramón Salinero on Unsplash

    gRPC: synchronous and asynchronous unary RPC in Java

    Microservices inter-process communication using gRPC

    gRPC for microservices communication

  • GraphQL
    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring GraphQL with @Controller, @SchemaMapping and @QueryMapping

    Spring for GraphQL : @SchemaMapping and @QueryMapping

    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

  • Kubernetes
    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Components of Kubernetes Architecture

    Components of Kubernetes Architecture

    Helm Chart: quick start your app deployment on Kubernetes

    Helm Chart: quick start your app deployment on Kubernetes

    gRPC load balancing on Kubernetes (using Headless Service)

    gRPC load balancing on Kubernetes (using Headless Service)

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

  • Java
    Java Streams: Stream Operation with Examples

    Java Streams: Stream Operation with Examples

    Java Streams: stream creation with examples

    Java Streams: stream creation with examples

    Garbage Collection

    Super Fast Garbage Collectors in Java

    Calculus

    Functional Programming in Java

No Result
View All Result
  • Login
  • Microservices
    • All
    • GraphQL
    • gRPC
    • Spring Boot
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    Distributed transaction in microservices using Saga

    Distributed Transactions in Microservices: implementing Saga with Temporal

    Temporal Workflow Orchestration

    Workflow Orchestration with Temporal and Spring Boot

    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

  • Spring Boot
    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful Microservices with Spring Boot and Kubernetes

    RESTful API Gateway with gRPC

    RESTful API Gateway with gRPC

  • gRPC
    gRPC Bidirectional Streaming with Code Example

    gRPC Bidirectional Streaming with Code Example

    gRPC Client Streaming

    gRPC Client Streaming

    gRPC Interceptor: unary interceptor with code example

    gRPC Interceptor: unary interceptor with code example

    gRPC: synchronous and asynchronous Server streaming RPC

    gRPC: synchronous and asynchronous Server streaming RPC

    Photo by Ramón Salinero on Unsplash

    gRPC: synchronous and asynchronous unary RPC in Java

    Microservices inter-process communication using gRPC

    gRPC for microservices communication

  • GraphQL
    GraphQL Directive

    GraphQL Directive

    Spring for GraphQL mutation

    Spring for GraphQL: Mutation

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring for GraphQL: How to solve the N+1 Problem?

    Spring GraphQL with @Controller, @SchemaMapping and @QueryMapping

    Spring for GraphQL : @SchemaMapping and @QueryMapping

    Spring Boot GraphQL service

    Getting started with Spring Boot GraphQL service

  • Kubernetes
    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Deploying a RESTful Spring Boot Microservice on Kubernetes

    Components of Kubernetes Architecture

    Components of Kubernetes Architecture

    Helm Chart: quick start your app deployment on Kubernetes

    Helm Chart: quick start your app deployment on Kubernetes

    gRPC load balancing on Kubernetes (using Headless Service)

    gRPC load balancing on Kubernetes (using Headless Service)

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Kind: quick start a multi-node local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

    Getting started with Minikube: deploying application on local Kubernetes cluster

  • Java
    Java Streams: Stream Operation with Examples

    Java Streams: Stream Operation with Examples

    Java Streams: stream creation with examples

    Java Streams: stream creation with examples

    Garbage Collection

    Super Fast Garbage Collectors in Java

    Calculus

    Functional Programming in Java

No Result
View All Result
Techdozo
No Result
View All Result
Home Microservices gRPC

gRPC for microservices communication

Pankaj by Pankaj
August 29, 2021
in gRPC, Microservices
Reading Time: 15 mins read
1
A A
0
Microservices inter-process communication using gRPC
3
SHARES
22.5k
VIEWS
Share on FacebookShare on TwitterShare on Linkedin

In the olden days, a software application was built as a large monolith, and It’s still being done. However, in recent times microservices architecture has become a popular choice for developing software applications. In a microservice architecture, the microservices often need to communicate with each other. Compared to the traditional RESTful web API, a gRPC based RPC framework can be a better alternative for microservices communication.

Do you want to know more about gRPC, the remote procedure call (RPC) framework used by companies like Netflix and Dropbox?

Let’s get started:

What is microservices architecture?

A microservice architecture consists of many (often hundreds) of small, autonomous, self-contained services. A microservice is built around business capability. Some of the important characteristics of microservice architecture are:

  • Microservices are modelled around business capabilities.
  • Microservices are independently deployable.
  • A microservices encapsulates the data it owns. If one microservice needs to get data from another, it should call API.
  • A microservice should be small in size.

Microservices inter-process communication

A microservices-based software system requires applications to talk to each other using an inter-process communication mechanism. Microservices can communicate with each other as

  • Synchronous communication (request-reply): In this pattern, a service calls an API exposed by another service and waits for the response. The API must have well-defined semantics and versioning.
  • Asynchronous communication: In this pattern, a service sends a message, without waiting for a response from another service. And, one or more services can process the message.

A most common way of implementing a request-reply style of communication is by using RESTful services, typically implemented as JSON payload over HTTP. However, RESTful services can be bulky, inefficient, and limiting for many use cases. The bulkiness of RESTful services is because of the fact that most implementation relies on JSON, a text-based encoding format. The JSON format uses lots of space compared to the binary format.

There are binary encoding formats of JSON (MessagePack, BSON, SMILE, etc.); however, their adoption is not widespread.

Another issue with using JSON-based API is that schema support is optional. The most common way for an application to advertise API is by using OpenAPI spec, but this is not tightly integrated with the RESTful architecture style. It’s very common to see OpenAPI spec and implementation drifting in due course.

Why gRPC for microservice communication?

To solve issues associated with RESTful services, we need a modern inter-process communication system that is scalable and more efficient than RESTful services. Enter gRPC, a modern, open-source RPC framework.

The gRPC framework is based on binary encoding format protocol buffer and implemented on top of HTTP/2. It’s strongly typed, polyglot, and provides both client and server-side streaming.

In gRPC, a client application can directly call a method on a distributed server application on a different machine as if it were a local method.

So, the question is, should you move all our APIs to use gRPC?

Probably No !!

Before we answer, let’s understand some facts about APIs. There are two types of APIs:

  • Public API: these APIs are consumed by client applications, typically browsers, mobile applications, or other applications. For example – GitHub public APIs.
  • Private API: these APIs are not exposed to the outside world, and it’s mainly used for inter-service communication within your application.

The de facto standard for using Public API is REST over HTTP. For private APIs, you can think of using gRPC; however, you must be aware of trade-offs associated with introducing a new technology stack vs gRPC benefits. Moreover, supporting gRPC on a browser-based application is not straightforward.

One of the possible gRPC-based architectures is to have API Gateway/BFF in front of the microservices and make all internal communication using gRPC.

A gRPC application architecture

Advantages of gRPC

There are many advantages of using gRPC. That’s why it’s widely adopted by companies like Netflix and Dropbox. Let’s understand some of the advantages.

Faster compared to JSON based RESTful APIs

The gRPC is much faster compared to traditional JSON-based REST APIs. The gRPC is based on binary protocol-buffer format, which is very lightweight compared to text-based formats such as JSON.

For example, JSON encoding takes 81 bytes for the below payload, and the same payload in protocol buffers takes 33 bytes (source – Chapter 4 – Designing Data-intensive Applications by Martin Kelpmann. If you haven’t read this book, you have missed something !!)


{
	"serName": "Martin",
	"favoriteNumber": 1337,
	"interests": [" daydreaming", "hacking"]
}

It’s possible to implement RESTful APIs on top of the protocol buffer, but why would you want to do that?

Another reason which makes gRPC faster is that it’s implemented on top of HTTP/2. How fast? Check this comparison of HTTP/1.1 vs HTTP/2.

Strong type and well-defined interface

gRPC introduces a well-defined service interface and strong type that helps us avoid run time errors. For the client application, it’s as good as calling the local method. For example, you can define a gRPC service as:


service ProductService {
  rpc getProduct(GetProductRequest) returns (GetProductResponse);
}

Also, you can call this from a gRPC client as:


var productResponse = productServiceBlockingStub.getProduct(productRequest);

As you can see, calling the gRPC server is as good as calling a local method.

Polyglot

gRPC supports multiple programming languages. You can write microservices in the programming language you deem fit and not worry about interoperability issues.

Stream support

The gRPC supports both client and server-side streaming. Enabling these features in your application is as simple as changing the service definition. For example, server-side streaming is enabled by just declaring a response with the stream keyword.


service ProductService {
  rpc getProduct(GetProductRequest) returns (stream GetProductResponse);
}

Other features

gRPC has in-built support for resiliency, authentication, encryption, compression, load-balancing, and error handling. The gRPC is a proud member of the Cloud Native Computing Foundation (CNCF), and many modern frameworks provide native support for gRPC.

Code sample

You can find the working code example of this article at GitHub . To run code, clone repository, and import grpc-example as Gradle project. To build the project and generate client and server stubs, run the command gradlew clean build. You can start the gRPC server in IDE by running the main method of ProductServer. The gRPC server runs on localhost:8081. To execute RPC, run the main method of the ProductClient from order-service.

Implementing gRPC client and server

Before we start, let’s try to understand some important concepts of gRPC. A gRPC application consists of three important components:

  • Protocol Buffer: it defines messages and services exposed by the server application. gRPC services send and receive data as Protocol Buffer (Protobuf) messages.
  • Server: the server application implements and exposes RPC services.
  • Client: the client application consumes RPC services exposed by the server.

What are protocol buffers?

Protocol buffers are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.

Google

Protocol buffers are nothing but interface definition language (IDL) used to define API contracts in gRPC. In gRPC, you define API contracts in .proto files.

You define gRPC APIs by declaring messages and services. For example, if the order-service (gRPC client) calls the product-service (gRPC server) to fetch information about the product by passing productId, then you can define service definition in the protocol buffer as :


syntax = "proto3";
package dev.techdozo.product.api;

message GetProductRequest {
  string productId = 1;
}

message GetProductResponse {
  string name = 1;
  string description = 2;
  double price = 3;
}

service ProductService {
  rpc getProduct(GetProductRequest) returns (GetProductResponse);
}

Let’s understand the different elements of the proto file.

Protobuf message

The message is a binary data structure exchanged between the client and the server. The message and service are declared in .proto files. If you want, you can create separate files for messages and services. For example, resources.proto for messages, and service.proto for service definition.

Field numbers, such as name = 1, are used to identify fields in the binary encoded data. This means you can’t change the field number from one version to another. Furthermore, this helps in backward and forward compatibility – clients and services can ignore field numbers they don’t know about.

Service

A service is a remote method that is exposed by the server. The client can use the generated stub to call the remote method on the server. In the above example, product-service exposes an RPC method rpc getProduct(GetProductRequest) returns (GetProductResponse);. This RPC call returns information about the Product as GetProductResponse .

Code generation

You can use protoc compiler to generate client and server code. The protoc compiler supports code generation in many different languages.

For our example, we will use Protobuf Gradle Plugin to generate source code in java. The protocol buffer plugin assembles the Protobuf Compiler (protoc) command line and use it to generate Java source files from the proto files. The generated java source files should be added to the sourceSet so that they can be compiled along with Java sources.


sourceSets {
    main {
        java {
            srcDirs 'build/generated/source/proto/main/grpc'
            srcDirs 'build/generated/source/proto/main/java'
        }
    }
}

Running command gradlew build generates source code in the directory build/generated/source/proto/main/grpc and build/generated/source/proto/main/java.

gRPC Server

The gRPC server implements services defined in the proto files and expose those as RPC API. In this example, we will treat the product microservice as a gRPC server and order microservice as the gRPC client.



In our case, the gRPC server exposes one RPC method rpc getProduct(GetProductRequest) returns (stream GetProductResponse).

Implementing service definition

After you have the server stub generated, you can implement the RPC service ProductService, as defined in the service.proto file.

To implement the business logic, you should override getProduct(..) method in the autogenerated abstract class ProductServiceGrpc.ProductServiceImplBase .


public class ProductService extends ProductServiceGrpc.ProductServiceImplBase {

  private final ProductRepository productRepository;

  public ProductService() {
    this.productRepository = new ProductRepository();
  }

  @Override
  public void getProduct(
      GetProductRequest request, StreamObserver<GetProductResponse> responseObserver) {


    var productId = request.getProductId();
    Optional<ProductInfo> productInfo = productRepository.get(productId);

    if (productInfo.isPresent()) {
      var product = productInfo.get();

      var getProductResponse =
          GetProductResponse.newBuilder()
              .setName(product.getName())
              .setDescription(product.getDescription())
              .setPrice(product.getPrice())
              .build();
      responseObserver.onNext(getProductResponse);
      responseObserver.onCompleted();
    } else {
      responseObserver.onError(new StatusException(Status.NOT_FOUND));
    }
   
  }
}

The above code fetches Product information from ProductRepository and calls onNext() on StreamObserver by passing the getProductResponse. The onCompleted() method notifies the stream about successful completion.

In case of an error, you can call onError() method by passing the appropriate error code.

Registering service

To expose the RPC service ProductService, you can create a gRPC server instance and register the service by calling the addService method. The server listens to the specified port and dispatches all requests to the relevant service.


public ProductServer(int port) {
    this.port = port;
    var productService = new ProductService();
    this.server = ServerBuilder.forPort(port).addService(productService).build();
}

Implementing gRPC client stub

The first thing we need to do to implement a gRPC client is to generate client stubs using the proto file defined in the server (product-service) application.


public class ProductClient {

  private final ProductServiceGrpc.ProductServiceBlockingStub productServiceBlockingStub;

  public ProductClient(String host, int port) {
    var managedChannel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
    this.productServiceBlockingStub = ProductServiceGrpc.newBlockingStub(managedChannel);
  }

  public void call() {

    var productRequest = GetProductRequest.newBuilder().setProductId("apple-123").build();
    var productResponse = productServiceBlockingStub.getProduct(productRequest);
    log.info("Received Product from server, info {}", productResponse);
  }

  public static void main(String[] args) {
    var client = new ProductClient("0.0.0.0", 8081);
    client.call();
  }
}

You can create a gRPC channel specifying the server address and port as ManagedChannelBuilder.forAddress(host, port).usePlaintext().build(). The channel represents a virtual connection to an endpoint to perform RPC.

You can create the client stub using the newly created channel as:


var managedChannel = ManagedChannelBuilder.forAddress(host,port).usePlaintext().build();
var productServiceBlockingStub = ProductServiceGrpc.newBlockingStub(managedChannel);

There are two types of client stubs:

  • Blocking: The BlockingStub, which waits until it receives a server response.
  • Non Blocking: The NonBlockingStub, which doesn’t wait for server response, but instead registers an observer to receive the response.

Here plaintext means we are setting up an unsecured connection between the client and server.

Summary

A gRPC-based RPC framework is a great choice for inter-process communication in microservices applications. Not only the gRPC services are faster compared to RESTful services, but also they are strongly typed. The Protocol Buffer, a binary format for exchanging data, is used for defining gRPC APIs. The gRPC is supported in many programming languages. Using code generation tools makes it easier to generate client and server stubs in the gRPC.

Tags: grpcjavamicroservices
Previous Post

Deploying a RESTful Spring Boot Microservice on Kubernetes

Next Post

gRPC: synchronous and asynchronous unary RPC in Java

Pankaj

Pankaj

Software Architect @ Schlumberger ``` Cloud | Microservices | Programming | Kubernetes | Architecture | Machine Learning | Java | Python ```

Related Posts

gRPC Bidirectional Streaming with Code Example
gRPC

gRPC Bidirectional Streaming with Code Example

February 17, 2023
gRPC Client Streaming
gRPC

gRPC Client Streaming

January 20, 2023
Distributed transaction in microservices using Saga
Microservices

Distributed Transactions in Microservices: implementing Saga with Temporal

November 8, 2022
Temporal Workflow Orchestration
Microservices

Workflow Orchestration with Temporal and Spring Boot

October 29, 2022

Discussion about this post

Recent Articles

gRPC Bidirectional Streaming with Code Example

gRPC Bidirectional Streaming with Code Example

February 17, 2023
gRPC Client Streaming

gRPC Client Streaming

January 20, 2023
Distributed transaction in microservices using Saga

Distributed Transactions in Microservices: implementing Saga with Temporal

November 8, 2022
Temporal Workflow Orchestration

Workflow Orchestration with Temporal and Spring Boot

October 29, 2022
  • Trending
  • Comments
  • Latest
Deploying a RESTful Spring Boot Microservice on Kubernetes

Deploying a RESTful Spring Boot Microservice on Kubernetes

August 18, 2021
Temporal Workflow Orchestration

Workflow Orchestration with Temporal and Spring Boot

October 29, 2022
gRPC Interceptor: unary interceptor with code example

gRPC Interceptor: unary interceptor with code example

April 30, 2022
Microservices inter-process communication using gRPC

gRPC for microservices communication

August 29, 2021
Calculus

Functional Programming in Java

0
Java Streams: stream creation with examples

Java Streams: stream creation with examples

0
Garbage Collection

Super Fast Garbage Collectors in Java

0
Java Streams: Stream Operation with Examples

Java Streams: Stream Operation with Examples

0
gRPC Bidirectional Streaming with Code Example

gRPC Bidirectional Streaming with Code Example

February 17, 2023
gRPC Client Streaming

gRPC Client Streaming

January 20, 2023
Distributed transaction in microservices using Saga

Distributed Transactions in Microservices: implementing Saga with Temporal

November 8, 2022
Temporal Workflow Orchestration

Workflow Orchestration with Temporal and Spring Boot

October 29, 2022
Facebook Twitter Pinterest

TECHDOZO

Simplifying modern tech stack!

Browse by Category

  • Bitesize
  • GraphQL
  • gRPC
  • Java
  • Kubernetes
  • Microservices
  • Spring Boot

Recent Articles

gRPC Bidirectional Streaming with Code Example

gRPC Bidirectional Streaming with Code Example

February 17, 2023
gRPC Client Streaming

gRPC Client Streaming

January 20, 2023

© 2023 Techdozo.

No Result
View All Result
  • Home
  • gRPC
  • Kubernetes
  • Microservices
  • GraphQL

© 2023 Techdozo.

Welcome Back!

Sign In with Google
OR

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In