gRPC Client 구현 과정 ( JAVA )

이준섭·2024년 7월 11일
0

gRPC

목록 보기
2/2
post-thumbnail

1. Protocol Buffer을 정의하는 '.proto'파일 작성

※ gRPC Server에서 작성한 .proto파일과 동일하게 작성한다.

  syntax = "proto3";

  package com.example.grpc;
  option java_outer_classname = "BiddingModel";

  message BidRequest {
    string userId = 1;
    int32 bidPrice = 2;
  }

  message BidResponse {
    int32 bidPrice = 1;
  }

  service BidService {
    rpc bidding(BidRequest) returns (BidResponse);
    rpc winBidding(BidRequest) returns (stream BidResponse);
    rpc streamBidding(stream BidRequest) returns (stream BidResponse);
  }

2. build.gradle 작성

  plugins {
      id 'java'
      id 'org.springframework.boot' version '3.2.5'
      id 'io.spring.dependency-management' version '1.1.4'
      // protobuf 플러그인
      id 'com.google.protobuf' version '0.8.15'
  }

  repositories {
      mavenCentral()
  }

  group = 'com.grpc'
  version = '0.0.1-SNAPSHOT'

  java {
      sourceCompatibility = '17'
  }

  configurations {
      compileOnly {
          extendsFrom annotationProcessor
      }
  }

  dependencies {
      implementation 'org.springframework.boot:spring-boot-starter'
      implementation 'org.springframework.boot:spring-boot-starter-web'
      implementation 'javax.annotation:javax.annotation-api:1.3.2'
      // grpc
      // grpc-java는 netty서버를 embedded하여 사용합니다
      implementation 'io.grpc:grpc-netty-shaded:1.36.0'
      implementation 'io.grpc:grpc-protobuf:1.36.0'
      implementation 'io.grpc:grpc-stub:1.36.0'

      // protobuf
      implementation "com.google.protobuf:protobuf-java-util:3.8.0"
      implementation "com.google.protobuf:protobuf-java:3.8.0"

      //mapstruct
      implementation "org.mapstruct:mapstruct:1.4.2.Final"
      implementation 'org.projectlombok:lombok-mapstruct-binding:0.2.0'

      // grpc test
      testImplementation group: 'io.grpc', name: 'grpc-testing', version: '1.36.0'
      compileOnly 'org.projectlombok:lombok'
      annotationProcessor 'org.projectlombok:lombok'
      annotationProcessor "org.mapstruct:mapstruct-processor:1.4.2.Final"
      testImplementation 'org.springframework.boot:spring-boot-starter-test'
  }

  protobuf {
      protoc {
          artifact = 'com.google.protobuf:protoc:3.12.0'
      }
      plugins {
          grpc {
              artifact = 'io.grpc:protoc-gen-grpc-java:1.36.0'
          }
      }
      generateProtoTasks {
          all()*.plugins {
              grpc {}
          }
      }
  }

  sourceSets {
      main {
          // 빌드된 폴더를 인텔리제이가 인식할수 있도록 소스폴더로 포함
          java {
              srcDirs += [ './build/generated/source/proto/main/grpc', './build/generated/source/proto/main/java' ]
          }
          // 프로토콜버퍼 파일의 위치를 지정
          proto {
              srcDir 'src/main/resources/proto'
          }
      }
  }

  jar {
      enabled = false
  }

3. Controller 작성

  @Slf4j
  @RestController
  @RequestMapping("/api/v1/client")
  @RequiredArgsConstructor
  public class GrpcClientController {
      private final GrpcClientService clientService;

      @PostMapping("/bidding")
      public BiddingModel.BidResponse bidding(@RequestBody GrpcClientRequest grpcClientRequest) throws Exception {
          return clientService.bidding(grpcClientRequest);
      }

      @PostMapping("/winBidding")
      public void winBidding(@RequestBody GrpcClientRequest grpcClientRequest) throws Exception {
          clientService.winBidding(grpcClientRequest);
      }

      @PostMapping("/streamBidding")
      public void streamBidding(@RequestBody GrpcClientRequest grpcClientRequest) throws Exception {
          clientService.streamBidding(grpcClientRequest);
      }

  }

4. Service 작성

  @Slf4j
  @Service
  @RequiredArgsConstructor
  public class GrpcClientService {

      private final BidServiceGrpc.BidServiceBlockingStub blockingStub;
      private final BidServiceGrpc.BidServiceStub stub;

      public BiddingModel.BidResponse bidding(GrpcClientRequest grpcClientRequest) {
          // 받아온 파라미터를 gRPC 모델로 매핑
          BiddingModel.BidRequest bidRequest = ClientMapper.instance.toBiddingModelRequest(grpcClientRequest);
          // 단방향 RPC 호출
          BiddingModel.BidResponse response = blockingStub.bidding(bidRequest);
          return response;
      }

      public void winBidding(GrpcClientRequest grpcClientRequest) {
          // 받아온 파라미터를 gRPC 모델로 매핑
          BiddingModel.BidRequest bidRequest = ClientMapper.instance.toBiddingModelRequest(grpcClientRequest);
          stub.winBidding(bidRequest, new StreamObserver<BiddingModel.BidResponse>() {

              @Override
              public void onNext(BiddingModel.BidResponse value) {
                  System.out.println(value);
              }

              @Override
              public void onError(Throwable t) {
                  throw new RuntimeException(t);
              }

              @Override
              public void onCompleted() {
                  System.out.println("서버 스트리밍 완료");
              }
          });
      }

      public void streamBidding(GrpcClientRequest grpcClientRequest) {
          // 받아온 파라미터를 gRPC 모델로 매핑
          BiddingModel.BidRequest bidRequest = ClientMapper.instance.toBiddingModelRequest(grpcClientRequest);

          StreamObserver<BiddingModel.BidRequest> requestStreamObserver = stub.streamBidding(new StreamObserver<BiddingModel.BidResponse>() {
              GrpcClientResponse grpcClientResponse = new GrpcClientResponse();
              @Override
              public void onNext(BiddingModel.BidResponse value) {
                  System.out.println(value);
              }

              @Override
              public void onError(Throwable t) {
                  throw new RuntimeException(t);
              }

              @Override
              public void onCompleted() {
                  System.out.println("양방향 스트리밍 완료");
              }
          });
          requestStreamObserver.onNext(bidRequest);
          requestStreamObserver.onNext(bidRequest);
          requestStreamObserver.onCompleted();
      }
  }

5. Config Bean 작성

  @Component
  @RequiredArgsConstructor
  public class ClientConfig {

      @Value("${grpc.host}")
      private String host;
      @Value("${grpc.port}")
      private Integer port;

      @Bean
      public BidServiceGrpc.BidServiceBlockingStub blockingStub() {
          ManagedChannel managedChannel = getChannel();
          return BidServiceGrpc.newBlockingStub(managedChannel);
      }

      @Bean
      public BidServiceGrpc.BidServiceStub stub() {
          ManagedChannel managedChannel = getChannel();
          return BidServiceGrpc.newStub(managedChannel);
      }

      private ManagedChannel getChannel() {
          ManagedChannel managedChannel = ManagedChannelBuilder.forAddress(host, port)
                  .usePlaintext()
                  .build();
          return managedChannel;
      }

  }

0개의 댓글