gRPC Spring Boot Integration

Overview:

In this tutorial, I would like to show you the gRPC Spring Boot Integration for inter microservices communication.

gRPC is a RPC framework implementation from google for client-server application development.  We have discussed gRPC, protobuf and their advantages for inter microservices communication in these articles before. If you have not read them, check them out in the below order.

As we have gained some knowledge on how gRPC works with these articles, now lets take a look at gRPC Spring Boot Integration.

Service Definition:

We are going to develop a simple Calculator Service using Spring Boot. That application will expose APIs which are defined through this Protobuf service definition.

service CalculatorService {
  // unary
  rpc findFactorial(Input) returns (Output) {};
  // server stream
  rpc getAllDoubles(Input) returns (stream Output) {};
  // client stream
  rpc sumAll(stream Input) returns (Output) {};
  // bi-directional stream
  rpc playUpTo100(stream Input) returns (stream Output) {};
}

High Level Architecture:

When we have multiple services, 1 service would act like an aggregator service which is responsible for orchestrating the request and make internal calls to other microservices and consolidate the responses and send back to the client. The aggregator service when it calls other microservices uses gRPC. The communication between front-end and aggregator will be REST. (We can also use gRPC-Web.)

In this demo, we would be having only 2 services as shown here by using the above mentioned service definition.


gRPC Course:

I learnt gRPC + Protobuf in a hard way. But you can learn them quickly on Udemy. Yes, I have created a separate step by step course on Protobuf + gRPC along with Spring Boot integration for the next generation Microservice development. Click here for the special link.


Project Set up:

  • Lets first create a multi module maven project with 3 modules.
    • proto-module
      • It contains the protocol buffers file (.proto)
    • calculator-service
      • It is the gRPC Spring Boot server which contains business logic
    • aggregator-service
      • It is the backend-for-frontend (BFF)
      • Exposes REST for outside world / browsers
      • Internal calls will be using gRPC

Proto-Module:

  • I keep the proto files in the proto-module as shown here.
  • If any other module needs the generated sources, they need to add this as a dependency.

Calculator-Service:

  • This will be a Spring Boot application with below maven dependencies.
<dependencies>
    <dependency>
        <groupId>net.devh</groupId>
        <artifactId>grpc-server-spring-boot-starter</artifactId>
        <version>2.9.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>proto-module</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>
  • This module adds the proto-module as the dependency.
  • The project structure is as shown here.

  • Service class
@GrpcService
public class CalculatorService extends CalculatorServiceGrpc.CalculatorServiceImplBase {

    // server sends multiples data one by one
    // input is 6, server will send 2, 4, 6, 8, 10, 12
    @Override
    public void getAllDoubles(Input request, StreamObserver<Output> responseObserver) {
        int index  = request.getNumber();
        IntStream.rangeClosed(1, index)
                .map(i -> i * 2) // add Thread.sleep to simulate time consuming operation
                .mapToObj(i -> Output.newBuilder().setResult(i).build())
                .forEach(responseObserver::onNext);
        responseObserver.onCompleted();
    }
}
  • This Spring Boot application exposes API via gRPC. Not REST endpoints.
  • I add the below entry in the application.properties.
grpc.server.port=6565

Aggregator-Service:

  • This will be another Spring Boot application with following dependencies. This application will act like client for the above calculator-service.
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>proto-module</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>net.devh</groupId>
        <artifactId>grpc-client-spring-boot-starter</artifactId>
        <version>2.9.0.RELEASE</version>
    </dependency>
</dependencies>
  • The project structure for the aggregator-service is as shown here.

  • The application.yaml contains the grpc server details. Here the calculator-service is a just a logical name to group the details and access it in the service class.
grpc:
  client:
    calculator-service:
      address: static://localhost:6565
      negotiationType: plaintext
  • In this service class implementation, Spring boot automatically injects a blocking stub to make the RPC request. This is where we use the logical name defined above. We can have multiple gRPC clients for multiple gRPC servers in an application.
@Service
public class AggregatorService {

    @GrpcClient("calculator-service")
    private CalculatorServiceGrpc.CalculatorServiceBlockingStub blockingStub;

    public Flux<Long> getAllDoubles(final int number){
        //  build input object
        Input input = Input.newBuilder()
                .setNumber(number)
                .build();

        return Flux.create(fluxSink -> {
            this.blockingStub.getAllDoubles(input)
                    .forEachRemaining(output -> fluxSink.next(output.getResult()));
            fluxSink.complete();
        });
    }
    
}
  • REST API
@RestController
@RequestMapping("/api")
public class AggregatorController {

    @Autowired
    private AggregatorService aggregatorService;

    @GetMapping("/doubles/{number}")
    public Flux<Long> getAllDoubles(@PathVariable int number){
        return this.aggregatorService.getAllDoubles(number);
    }

}

gRPC Spring Boot Demo:

  • Lets start both Calculator Service and the Aggregator Service
  • Send a request to aggregator service as shown here. The request is forwarded to the Calculator service which would be a RPC and aggregator service receives the response which in turn sent back to the client.

Summary:

We were able to successfully integrate Spring boot with gRPC. We just explored server streaming example here. We can implement other RPCs as well the same way as we had demonstrated here.

The source code is available here.

Happy learning 🙂

Share This:

5 thoughts on “gRPC Spring Boot Integration

  1. I’ve just forwarded this onto a colleague who has been doing a little research on this. thanks for this topic here on your web site.

  2. Having read this I thought it was extremely informative. I appreciate you taking the time and effort to put this short article together. I once again find myself personally spending way too much time both reading and commenting. But so what, it was still worthwhile!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.