
There are many ways of communication between services. We can make use of REST/SOAP web services, RPCs or the more advanced technique gRPC with less latency.
gRPC provides better features compare to other ways of message exchange. So, for communication between microservices we can use gRPC for example.
Features of gRPC:
- The gRPC uses HTTP/2 protocol as transport for communication which is faster than REST
- Message exchanged in the form of Protocol Buffers (Google’s mature open source mechanism for serializing structured data)
- We can generate the code using
.protofiles - Allows bi-directional streaming
- Requires gRPC -web to invoke
gRPC Architecture:
The architecture of gRPC is as below. It can be seen that server and client can be written in different languages and gRPC will take care of the conversions required.

gRPC Server implementation:
gRPC server is the application that exposes gRPC services to be consumed by gRPC client.
We will be using gradle as build tool here and need below plugins, dependencies and protobuf settings in build.gradle file:
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.5'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'com.google.protobuf' version '0.8.14'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation group: 'io.grpc', name: 'grpc-netty', version: '1.50.2'
implementation group: 'io.grpc', name: 'grpc-protobuf', version: '1.50.1'
implementation group: 'io.grpc', name: 'grpc-stub', version: '1.50.1'
implementation group: 'net.devh', name: 'grpc-server-spring-boot-starter', version: '2.13.1.RELEASE'
}
protobuf {
generatedFilesBaseDir = "$projectDir/src/main/java/generated"
protoc {
artifact = 'com.google.protobuf:protoc:3.10.1'
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.25.0'
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
Add .proto file in main/proto folder with below contents.
HelloService.proto =>
syntax = "proto3";
option java_multiple_files = true;
package com.example.grpcserver;
service HelloService {
rpc hello(HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string firstName = 1;
string lastName = 2;
}
message HelloResponse {
string greeting = 1;
}
- proto3: The first line of the file specifies that you’re using
proto3syntax. This must be the first non-empty, non-comment line of the file. If not provided, protocol buffer compiler will assume it asproto2 - java_multiple_files:
- If set to false, only a single
.javafile will be generated for this.protofile, and all the Java classes/enums/etc. generated for the top-level messages, services, and enumerations will be nested inside of an outer class. - If set to true, separate
.javafiles will be generated for each of the Java classes/enums/etc. generated for the top-level messages, services, and enumerations, and the wrapper Java class generated for this.
3. package: where the generated code need to be stored.
4. service: provide the required service and method names( in our case, we have given hello(), taking HelloRequest as parameter and returns HelloResponse as return type whose contents also the part of .proto file).
More details on the syntax of .proto files can be found here
Run gradle clean build to generate the files. The below files will be generated in the configured path.

The set of files will be generated. We need to extend the class HelloServiceGrpc.HelloServiceImplBase in generated folder and provide implementation for hello() method. Annotate the class with @GrpcService to mark a gRPC service implementation for automatic inclusion in your server.
package com.example.grpcserver.service;
import com.example.grpcserver.HelloRequest;
import com.example.grpcserver.HelloResponse;
import com.example.grpcserver.HelloServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
@GrpcService
public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void hello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
System.out.println("inside overriden method hello()");
HelloResponse response = HelloResponse.newBuilder().setGreeting("Hello "+ request.getFirstName()+" "+request.getLastName()+". Welcome").build();
System.out.println("returning :"+response);
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
Test the service using BloomRPC:
One of the ways to test gRPC service method is using BloomRPC application. We need to add the .proto file in server to bloomRPC and provide required parameters. And hit the play button. If everything is fine, you will get the response in right side as below:

By default the gRPC server port is 9090. If any other port need to be used (e.g.: 8080 ), add below in application.properties file:
grpc.server.port=8080
gRPC client implementation(another microservice):
We need below plugins, dependencies and protobuf settings in build.gradle file:
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.5'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'com.google.protobuf' version '0.8.14'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation group: 'io.grpc', name: 'grpc-netty', version: '1.50.2'
implementation group: 'io.grpc', name: 'grpc-protobuf', version: '1.50.1'
implementation group: 'io.grpc', name: 'grpc-stub', version: '1.50.1'
implementation group: 'net.devh', name: 'grpc-client-spring-boot-starter', version: '2.13.1.RELEASE'
}
protobuf {
generatedFilesBaseDir = "$projectDir/src/main/java/generated"
protoc {
artifact = 'com.google.protobuf:protoc:3.10.1'
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.25.0'
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
Add the same .proto file in main/proto folder.
In application.properties file, add gRPC server address and negotiation type:
grpc.client.hello-service.address=static://localhost:9090
grpc.client.hello-service.negotiation-type=plaintext
NegotiationType identifies the negotiation used for starting up HTTP/2. More details on can be found here.
Call the gRPC service as below:
package com.example.grpcclient.client;
import org.springframework.stereotype.Service;
import net.devh.boot.grpc.client.inject.GrpcClient;
@Service
public class GrpcClientClass {
@GrpcClient("hello-service")
private com.example.grpcserver.HelloServiceGrpc.HelloServiceBlockingStub helloServiceBlockingStub;
public void testingGRPC() {
com.example.grpcserver.HelloRequest helloRequest = com.example.grpcserver.HelloRequest.newBuilder().setFirstName("Mike").setLastName("John").build();
com.example.grpcserver.HelloResponse response = helloServiceBlockingStub.hello(helloRequest);
System.out.println("response:"+response);
}
}
In above code, we are invoking the “hello-service”(note: the name is given in application.properties file in client side) service from gRPC server using @GrpcClient annotation. We are forming the HelloRequest object to invoke the hello() method in gRPC server.
The complete code for gRPC server can be found on Github here and for gRPC client, here.
References:
- https://www.oreilly.com/library/view/grpc-up-and/9781492058328/ch01.html
- https://developers.google.com/protocol-buffers/docs/proto3
Thank you for reading. Happy exploring!!!