gRPCとKotlin
1. 序章
gRPCは、Googleが開発したオープンソースのRPC(リモートプロシージャコール)プラットフォームであり、あらゆる種類の環境およびデータセンター間で高性能で効率的な通信を提供します。 さらに、負荷分散、トレース、ヘルスチェック、および認証のgRPCのプラグイン可能なサポートにより、分散コンピューティングおよびマイクロサービスで使用するのに適した候補になります。
gRPCでは、クライアントアプリケーションは、分散アプリケーションとサービスの複雑さを隠す生成されたスタブを使用して、サーバーアプリケーション上のメソッドを呼び出します。
このチュートリアルでは、gRPCコンポーネントについて説明し、KotlinでgRPCサーバーとクライアントを実装する方法を説明します。
2. コンポーネント
gRPCはサービス定義から始まります。 サービス定義はサービスのインターフェースであり、メソッド、パラメーター、および期待される戻りタイプが含まれています。
次に、定義されたサービスインターフェイスに基づいて、クライアントはスタブを使用してサーバーを呼び出します。 一方、サーバーはインターフェースのサービスを実装し、gRPCサーバーを実行してクライアントの要求を処理します。
gRPCはデフォルトで、サービス定義とペイロードを記述するためのインターフェース記述言語としてProtobufを使用します。 ただし、 Protobuf の代わりに、Gsonなどの他のライブラリを使用してエンコードおよびデコードすることもできます。
gRPCがどのように機能するかをある程度理解したので、実装を見てみましょう。
3. 依存関係
gRPCの依存関係をPOMに追加することから始めましょう:
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>1.46.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.39.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.46.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-kotlin-stub</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-kotlin</artifactId>
<version>3.18.1</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.18.1</version>
</dependency>
4. プロトファイル
次に、.protoファイルでサービスを定義しましょう。 このチュートリアルでは、Javaチュートリアルで以前に使用したものと同じサービス定義を使用します。
syntax = "proto3";
package com.baeldung.grpc.helloworld;
option java_multiple_files = true;
service HelloService {
rpc hello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
これらのプロトファイルをコードで使用するには、それらのスタブを作成する必要があります。 この目標を達成するために、プロトコルバッファコンパイラprotocを使用します。
protoc --plugin=protoc-gen-grpc-java=build/exe/java_plugin/protoc-gen-grpc-java \
--grpc-java_out="$OUTPUT_FILE" --proto_path="$DIR_OF_PROTO_FILE" "$PROTO_FILE"
さらに、以下に示すように、このスタブ作成ステップをpom.xmlに埋め込むという簡単なオプションがあります。
5. Mavenプラグイン
次に、 org.xolstice.maven.plugins:protobuf-maven-pluginプラグインをpom.xml に追加して、プロトからリクエスト、レスポンス、スタブを作成できるようにします。 Maven compileゴールを実行するときのファイル。
これは、grpc-kotlin実装を利用します。
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
<protocPlugins>
<protocPlugin>
<id>grpc-kotlin</id>
<groupId>io.grpc</groupId>
<artifactId>protoc-gen-grpc-kotlin</artifactId>
<version>${grpc.kotlin.version}</version>
<classifier>jdk7</classifier>
<mainClass>io.grpc.kotlin.generator.GeneratorRunner</mainClass>
</protocPlugin>
</protocPlugins>
</configuration>
</execution>
</executions>
</plugin>
6. サーバーの実装
サービスの機能を実装するために、HelloServiceCoroutineImplBaseをオーバーライドすることから始めましょう。
class HelloService : HelloServiceGrpcKt.HelloServiceCoroutineImplBase() {
override suspend fun hello(request: HelloRequest): HelloReply {
return HelloReply.newBuilder()
.setMessage("Hello, ${request.name}")
.build()
}
}
次に、HelloServiceを使用してgRPCサーバーを起動できます。
fun helloServer() {
val helloService = HelloService()
val server = ServerBuilder
.forPort(15001)
.addService(helloService)
.build()
Runtime.getRuntime().addShutdownHook(Thread {
server.shutdown()
server.awaitTermination()
})
server.start()
server.awaitTermination()
}
fun main(args: Array<String>) {
helloServer()
}
7. クライアントの実装
クライアントを設定するには、 ManagedChannel :を作成しましょう。
val channel = ManagedChannelBuilder.forAddress("localhost", 15001)
.usePlaintext()
.build()
gRPCチャネルを使用して、クライアントは指定されたホストとポート上のgRPCサーバーに接続します。
それでは、スタブを作成しましょう。
val stub = HelloServiceGrpc.newBlockingStub(channel)
最後に、リクエストを作成してサーバーを呼び出しましょう。
val response = stub.hello(HelloRequest.newBuilder().setName("Baeldung").build())
ここでは、ブロッキングスタブを作成しますが、futureスタブまたは非同期スタブのオプションもあります。
将来のスタブを呼び出して、次のように応答を取得できます。
HelloServiceGrpc.newFutureStub(channel)
さらに、非同期スタブを作成し、コールバックでリアクティブな方法で応答を取得できます。
HelloServiceGrpc.newStub(channel).hello(
HelloRequest.newBuilder().setName("Baeldung").build(), object: StreamObserver<HelloReply> {
override fun onNext(response: HelloReply?) {
//consume response
}
override fun onError(throwable: Throwable?) {
//handle error
}
override fun onCompleted() {
//on complete
}
}
)
8. 結論
この記事では、gRPCと、Kotlinを使用してサーバー側とクライアント側にgRPCを実装する方法について説明しました。
いつものように、この記事の完全なソースコードは、GitHubでから入手できます。