Site icon Vinsguru

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:

Proto-Module:

Calculator-Service:

<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>

@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();
    }
}
grpc.server.port=6565

Aggregator-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>

grpc:
  client:
    calculator-service:
      address: static://localhost:6565
      negotiationType: plaintext
@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();
        });
    }
    
}
@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:

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:

Exit mobile version