GRPC for Spring Boot Microservices
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.
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.
- GRPC Server App and
- 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();
}
}
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();
}
}
Alright, now let’s watch how it works.
Let’s run both of your services.
After that just call the ping end point.
GET http://localhost:8081/ping
It will hit your client endpoint and from there, it will call the server side ping using your proto buf format. And the server will respond with a pong.
You can get the complete source code from
Follow my profile to get more like this.
Next : How to do RSocket communication with spring boot microservices.
Keep in touch.