daisuzz.log

gRPCをつかったSpring Bootアプリケーションをつくってみる

概要

gRPCに興味があったので、Spring Bootを使ったサンプルアプリケーションを実装してみました。

gRPCとは

詳しくは、Guides – gRPC をみてください。

  • Googleが開発したRPCを実現するプロトコル
  • HTTP/2上で動作する
  • デフォルトでは、Protocol Buffersをつかってserialize/deserializeを行う

という特徴があります。

gRPCを利用することで、通信の高速化が期待できたり、仕様からコードを自動生成することができ、開発のコストを下げることできます。

以降は、Spring BootアプリケーションでgRPCを導入した手順について書いていきます。

やったこと

やったことは、以下の通りです。

  • Springプロジェクトの作成
  • build.gradleの修正
  • .protoファイルの作成
  • 自動生成
  • gRPCサーバの実装
  • gRPCクライアントの実装
  • 動作確認

環境は、

  • Java8

  • Spring Boot 2.0.2.RELEASE

  • Gradle 4.6

です。

サンプルプログラムは以下にあります。 github.com

以下、ひとつずつ説明していきます。

Springプロジェクトの作成

まずは、Spring Initiilzrでプロジェクトを作成します。

build.gradleの修正

プロジェクトが作成できたら、build.gradleを修正します。

buildscript {
    ext {
        springBootVersion = '2.0.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath('com.google.protobuf:protobuf-gradle-plugin:0.8.3')
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'com.google.protobuf'

group = 'com.dais39'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    jcenter()
    mavenCentral()
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.lognet:grpc-spring-boot-starter:2.3.2')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:3.2.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'
        }
    }
}

.protoファイルの作成

.protoファイルを作成していきます。 gRPCでは、.protoファイルで雛形を定義しておき、それを元にgRPCサーバとクライアントのコードを自動生成する流れになります。

自動生成

gradleコマンドで.protoファイルからコードを自動生成します。

$ ./gradlew generateProto

コマンドを実行するとbuild/generated/source/proto/main/配下にgrpcとjavaパッケージが作成されていると思います。

gRPCサーバの実装

自動生成されたbuild/generated/source/proto/main/grpc/配下にあるxxxxGrpc.xxxxImplBaseクラスを継承したクラスを作成します。 Spring Bootの場合は、継承したクラスに@GRpcServiceをつけると必要な設定はSpring Bootがやってくれます。

package com.dais39.samplegrpcspringboot;

import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.stub.StreamObserver;
import org.lognet.springboot.grpc.GRpcService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SampleGrpcSpringbootApplication {

    public static void main(String[] args) {
        SpringApplication.run(SampleGrpcSpringbootApplication.class, args);
    }

    @GRpcService
    public static class GreeterService extends GreeterGrpc.GreeterImplBase {
        @Override
        public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
            HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + request.getName()).build();
            responseObserver.onNext(reply);
            responseObserver.onCompleted();

        }
    }
}

gRPCクライアントの実装

gRPCサーバを呼ぶクライアントを実装します。 今回は、Spring MVCの ControllerからgRPCサーバを呼ぶよう実装してみます。

package com.dais39.samplegrpcspringboot;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SampleController {

    @GetMapping("/grpc/{name}")
    public String hello(@PathVariable String name) {
        ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 6565)
                .usePlaintext(true)
                .build();

        GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);

        HelloRequest request = HelloRequest.newBuilder()
                .setName(name)
                .build();

        HelloReply reply = stub.sayHello(request);

        System.out.println("Reply: " + reply);

        return reply.getMessage();
    }
}

動作確認

まず、gRPCサーバを起動し、その後、gRPCクライアントから接続します。 今回はgRPCサーバもgRPCクライアントと同時に起動できるので、↓のコマンドを実行して、ブラウザでlocalhost:8080/grpc/hoge とアクセスすると、結果が確認できると思います。

$ ./gradlew build
$ java -jar build/libs/sample-grpc-springboot-0.0.1-SNAPSHOT.jar

おわりに

今回は、gRPCに触れてみようということでSpring Bootと併用したアプリケーションの実装をしてみました。 なかなか使い所がイメージできていないので、これからもう少し利用例を調べていきたいと思います。

参考資料

JavaでgRPC導入のためのポイント - Qiita

Spring BootでgRPCする - Qiita

GitHub - LogNet/grpc-spring-boot-starter: Spring Boot starter module for gRPC framework.

gRPC – A high-performance, open source universal RPC framework

Protocol Buffers  |  Google Developers