GRPC for Spring Boot Microservices

Sajeer Babu
4 min readSep 21, 2019

So, let’s make something on GRPC for Spring Boot.

I’m going to tell you how you could make two micro services communicating each other efficiently and fast.

Normally we can do it through the API calls, but if your services are on the same host, using API calls will be the less efficient and slowest method.

Don’t worry, we have some efficient methods for this, After a long research I found in two ways we can easily do this.

  1. GRPC

gRPC is a modern open source high performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.
— Picked from
GRPC Wbsite

Please refer some GRPC and proto buf articles so that you will get a good overview on those.

2. RSocket

RSocket is a binary protocol for use on byte stream transports such as TCP, WebSockets, and Aeron.

It enables the following symmetric interaction models via async message passing over a single connection:

request/response (stream of 1)

request/stream (finite stream of many)

fire-and-forget (no response)

channel (bi-directional streams)

— Picked from RSocket Website

I will explain RSocket in my upcoming Story. For now, we can go with GRPC.

So, Let’s code.

At first you have to create two spring boot projects.

  1. GRPC Server App and
  2. GRPC Client App

I’m depending Spring Initializr for this as it is much easier.

Server App

Add below dependencies to your pom.xml

<!-- For both -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>2.5.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- For the server (only) -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>2.5.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-autoconfigure</artifactId>
<version>2.5.1.RELEASE</version>
<type>pom</type>
</dependency>

Add below extension and plugins to the build section

<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

Mension the server port number and GRPC port number inside application.properties

server.port=8081
grpc.server.port=9090

Create a proto buf file like below

src/main/proto/PingPongService.proto

syntax = "proto3";
option java_multiple_files = true;
package com.example.grpc.server.grpcserver;
message PingRequest {
string ping = 1;
}
message PongResponse {
string pong = 1;
}
service PingPongService {
rpc ping(PingRequest) returns (PongResponse);
}

Once the proto file is created, you must package your maven project, so that it will generate the classes for you proto inside your target folder.

mvn clean package -Dmaven.test.skip=true

After that you need to create an implementation class for your proto service.

@GrpcService
public class PingPongServiceImpl extends PingPongServiceGrpc.PingPongServiceImplBase {
@Override
public void ping(
PingRequest request, StreamObserver<PongResponse> responseObserver) {
String ping = new StringBuilder()
.append("pong")
.toString();
PongResponse response = PongResponse.newBuilder()
.setPong(ping)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
See my gist

Client App

Add below dependencies to your pom.xml

<!-- For both -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>2.5.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- For the client (only) -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>2.5.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
</exclusion>
</exclusions>
</dependency><dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-autoconfigure</artifactId>
<version>2.5.1.RELEASE</version>
<type>pom</type>
</dependency>

Add below extension and plugins to your build section in pom.xml

<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

Mension the server port number and GRPC port number inside application.properties

server.port=8081
grpc.server.port=9090

Create a proto buf file like below

src/main/proto/PingPongService.proto

syntax = "proto3";
option java_multiple_files = true;
package com.example.grpc.server.grpcserver;
message PingRequest {
string ping = 1;
}
message PongResponse {
string pong = 1;
}
service PingPongService {
rpc ping(PingRequest) returns (PongResponse);
}

Once the proto file is created, you must package your maven project, so that it will generate the classes for you proto inside your target folder.

mvn clean package -Dmaven.test.skip=true

After all these, create a service class which can be used to ping the server app.

@Service
public class GRPCClientService {
public String ping() {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 9090)
.usePlaintext()
.build();
PingPongServiceGrpc.PingPongServiceBlockingStub stub
= PingPongServiceGrpc.newBlockingStub(channel);
PongResponse helloResponse = stub.ping(PingRequest.newBuilder()
.setPing("")
.build());
channel.shutdown(); return helloResponse.getPong();
}
}

Now you will be able to ping the server and will get pong in reverse if you call this ping method.

Now you have to create an endpoint for ping.

@RestController
public class PingPongEndpoint {
GRPCClientService grpcClientService; @Autowired
public PingPongEndpoint(GRPCClientService grpcClientService) {
this.grpcClientService = grpcClientService;
}
@GetMapping("/ping")
public String ping() {
return grpcClientService.ping();
}
}
See my gist

--

--