1
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SpringBootでgRPCやってみた

Last updated at Posted at 2019-09-30

SpringBootでgRPCの初期設定を行った際のメモ

build.gradle
// プラグイン追加
apply plugin: 'com.google.protobuf'

// 下記追加
protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:3.10.0"
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.4.0'
        }
    }
    generateProtoTasks {
        all()*.plugins {
            grpc {}
        }
    }
}
sourceSets {
    main {
        java {
            srcDirs 'build/generated/source/proto/main/grpc'
            srcDirs 'build/generated/source/proto/main/java'
        }
    }
}
dependencies {
    implementation('io.github.lognet:grpc-spring-boot-starter:3.4.1')
}

proto作成

Company.proto

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.hira.test.grpc";
option java_outer_classname = "CompanyProto";

package company;

// サービスメソッド定義
service Company {
    // 取得
    rpc Find (CompanyFindRequest) returns (CompanyFindReply);
    // 登録
    rpc Create (CompanyCreateRequest) returns (CompanyCreateReply);
    // 更新
    rpc Update (CompanyUpdateRequest) returns (CompanyUpdateReply);
    // 削除
    rpc Delete (CompanyDeleteRequest) returns (CompanyDeleteReply);
}

// 会社
message Company {
    // ID
    int32 id = 1;
    // 会社名
    string name = 2;
    // 住所
    string address = 3;
    // 電場番号
    string tel = 4;
}

// 付属情報
message Option {
     // 登録日時
     string createDt = 1;
     // 登録ユーザー
     string createUser = 2;
     // 更新日時
     string updateDt = 1;
     // 更新ユーザー
     string updateUser = 2;
}

// 取得リクエスト定義
message CompanyFindRequest{
    string id= 1;
}

// 取得レスポンス定義
message CompanyFindReply {
    Company company = 1;
    Option option = 2;
}

・・・(略)

Protoファイルをクライアントサイドとサーバサイドそれぞれでソース自動生成を行う。

GradleのgenerateProtoコマンドを実行するとbuild/generated/source/proto/main/配下に必要なソースが自動生成される。

サーバサイドの実装

CompanyGrpcService.java

@GRpcService
public class CompanyGrpcService extends CompanyServiceGrpc.CompanyServiceImplBase {

  // 会社リポジトリ
  @Autowired
  CompanyRepository companyRepository;

	/**
	 * 会社取得.
	 */
	@Override
	public void find(CompanyFindRequest request, StreamObserver<CompanyFindReply> responseObserver) {
		
		try {
			
	        // 会社取ID
			Company company = companyRepository.find(request.getId());
			
			CompanyFindReply.Builder builder = CompanyFindReply.newBuilder();
			
			if (company == null) {
				responseObserver.onError(new StatusException(Status.NOT_FOUND));
			} else {
				Company.Builder companyBuilder = builder.getCompanyBuilder();
				Option.Builder optionBuilder = builder.getOptionBuilder();
				companyBuilder.setId(company.getId());
				companyBuilder.setName(company.getName());

				builder.setPartnerCompany(partnerCompanyBuilder);
				builder.setOption(optionBuilder);

				responseObserver.onNext(builder.build());
				responseObserver.onCompleted();
			}
	        
		} catch(Exception e) {
			
			StatusRuntimeException exception = Status.INTERNAL
                    .withDescription(e.getMessage())
                    .withCause(e)
                    .asRuntimeException();
			
			responseObserver.onError(exception);
			
		}
}

クライアント(呼び出し)の実装

接続先のホストとポートを設定

application.properties
app.grpc.test.url=xxx.xxx.xxx.xxx
app.grpc.test.port=xxxx
AppConfig.java
@Component
@ConfigurationProperties(prefix = "app")
@Data
public class AppConfig {
   private Map<String, String> grpc;
}

ManagedChannelは、予め初期化しておいて呼び出す。

GrpcConfig.java
@Component
@Data
public class GrpcConfig {
   
   @Autowired
   AppConfig config;
   
   private ManagedChannel channelTest;
   
   @PostConstruct
   void initGrpcManagedChannel() {
   	channelTest = ManagedChannelBuilder
   			.forAddress(
   				config.getGrpc().get("test.url"), 
   				Integer.parseInt(config.getGrpc().get("test.port")))
               .usePlaintext(true)
               .build();
   }
}
CompanyMaintenanceService.java

@service
public class CompanyMaintenanceService {
  @Autowired
  GrpcConfig grpcConfig;

  public Company find(int id) {
      ManagedChannel channel = grpcConfig.getChannelTest();
      CompanyServiceGrpc.CompanyServiceBlockingStub stub = CompanyServiceGrpc.newBlockingStub(channel);
      // リクエスト作成
      CompanyFindRequest request = 
             CompanyFindRequest.newBuilder()
             .setId(id)
             .build();
      try {
      // リクエスト実行
      CompanyFindReply reply = stub.find(request);
      // 結果取得
          Company company = reply.getCompany();
          Option option = reply.getOption();

      ・・・(

      } catch (StatusRuntimeException e) {
          if(Status.NOT_FOUND.getCode() == e.getStatus().getCode()) {
              // 404の処理
          }
      }
  }
}

Protoのドキュメント化

protoc-gen-docを利用してProtoファイルからHTMLドキュメントを生成

protoc.exe --doc_out=html,index.html:doc proto/*.proto

所感

リクエストとレスポンスのパラメータ情報の定義の簡単さや、protoファイルによる定義でソースやドキュメントを自動出力できるためクライアントとサーバの定義共有が容易。

1
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?