masato-ka's diary

日々思ったこととか、やったことの備忘録。

grpc-spring-boot-starterでSpringBootへgRPCを導入する。

# この記事について この記事ではgrpc-spring-boot-starterを使ってSpringBootでgRPCを利用する方法について記載します。主に自分向けの備忘録的記事となります。

プロジェクトの設定

ビルドツールはMavenを利用します。SpringBootのライブラリ作成後、pomのdependenciesに以下を追加して依存関係にgrpc-spring-boot-starterを追加します。 grpc-spring-boot-starterはgRPCをSpringBootで利用できるようにするAutoConfigurationを実行します。

<dependencies>
        <dependency>
            <groupId>io.github.lognet</groupId>
            <artifactId>grpc-spring-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
 </dependencies>

ビルドを実行するプラットフォームを特定するためにプラグイン拡張を追加します。プロトコルバッファをビルドするためのprotocコマンドダウンロードに利用します。

<build>
...
<extensions>
      <extension>
           <groupId>kr.motd.maven</groupId>
           <artifactId>os-maven-plugin</artifactId>
           <version>1.5.0.Final</version>
      </extension>
</extensions>
...
</build>

さらにpurotobuf-maven-pluginを追加することで、Mavenのビルドプロセスの中でプロトコルバッファをコンパイルできるようにします。

<build>
...
<plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.6.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.18.0:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
...
</plugins>
</build>

上記でgRPC導入の設定は完了です。

gRPCのインタフェース定義

gRPCではprotoファイルと呼ばれるファイルでRPCの定義を記述します。記述されたprotoファイルからprotobuf-manve-plugin(実際にはprotocコマンド)がgRPCのサーバ側の抽象クラスとクライアントコードを自動生成します。

protoファイルの作成

以下のようなprotoファイルで定義します。 先頭の「option java_package」で生成後のコードのパッケージを定義します。プロジェクトのパッケージに合わせて適宜変更します。

syntax = "proto3";

option java_multiple_files = true;
option java_package = "ka.masato.grpc.demo.grpcmavendemo";
option java_outer_classname = "GreetClass";

package greet;

service Greet{
    rpc greeting (GreetRequest) returns (GreetResponse);
}


message GreetRequest{
    string value = 1;
}

message GreetResponse{
    string value = 1;
}

protoファイルの文法については以下を参照ください。

developers.google.com

protoファイルのビルド

protoファイルのビルドは前述のようにMavenのビルドプロセスの中で実行れます。以下のようにビルドを実行します。

$ mvnw clean package install

実行後、target/generated-souces/protobuf配下に生成されたコードが格納されています。IntelliJ IDEAで実行した際にはclassパスにも追加されているはずのなので、そのまま、srcフォルダ配下のパッケージから参照することができます。

gRPCの実装

生成されたコードをベースにサーバとクライアントを実装します。

サーバ側の実装

生成されたコードに含まれるGreetGrpc.GreetImplBaseを継承したクラスを作成します。この抽象クラスにはprotoファイルで定義したサービスがメソッドとして定義されており、これをオーバライドすることでAPIを実装します。また、継承クラスにはgrpc-spring-boot-starterで定義されている@GRpcServiceアノテーションをつけることで、gRPCのサーバとして登録されます。

@GRpcService
public class endpoint extends GreetGrpc.GreetImplBase{

    @Override
    public void greeting(GreetRequest request, StreamObserver<GreetResponse> responseObserver) {

        String value = request.getValue();
        GreetResponse greetResponse = GreetResponse.newBuilder().setValue("Greeting!"+ value).build();
         responseObserver.onNext(greetResponse);
         responseObserver.onCompleted();

    }
}

クライアントの実装

クライアント側ではスタブを作成し、スタブ経由でサービス側のメソッドを呼び出します。正確かはわかりませんがManagedChannelはgrpc-spring-boot-starterでbean定義されていると思います。

public class GreetClient {

    private final GreetGrpc.GreetBlockingStub stub;


    public GreetClient(ManagedChannel managedChannel) {
        this.stub = GreetGrpc.newBlockingStub(managedChannel);
    }

    public String getHello(){
        GreetRequest greetRequest = GreetRequest.newBuilder().setValue("Hello").build();
        GreetResponse greetResponse = this.stub.greeting(greetRequest);
        return greetResponse.getValue();

    }

}

まとめ

grpc-spring-boot-starterを使うとSpringBootで簡単にgRPCを実装することができました。また、proto-buf-mavenプラグインを利用することで、Mavenのビルドプロセスの中でプロトコルバッファのファイルからgRPCのコードを自動生成することができました。gRPCはprotoファイルで定義した内容からサービスの実装インタフェースと対応するクライアントコードを自動生成でき、サービス間通信のインターフェースを実装と定義を紐付ける良い方法だと思います。実際の開発にはprotoファイルの管理やなど実装以外に工夫が必要そうです。