My External Storage

Jan 4, 2018 - 4 minute read - Comments - Go gRPC

[Go][gRPC]Server Reflection Tutorialをやってみた

前回のgRPCのクイックスタートをやったときにサーバーリフレクションのことがよくわからなかった。サーバーリフレクションにもチュートリアルがあったのでやってみた。

TL;DR

  • サーバーリフレクションを使うと実行中のサーバからプロトコルバッファーの定義を取得したり、実行出来るようになる。
  • Goで利用するには、grpc.NewServer()のあとで通常のプロトコルバッファーのRegisterをした後reflection.Registerメソッドを呼ぶだけ
  • チュートリアルの手順通りに行うとc++のクライアントからサーバのプロトコルバッファーを確認することができる。

Server Reflectionとは

GRPC Server Reflection Protocol
https://github.com/grpc/grpc/blob/master/doc/server-reflection.md

サーバーリフレクションはクライアントのコマンドラインからgRPCの定義の取得あるいは実行を可能にするgRPCサーバの拡張機能。サーバーリフレクションによってcurlライクなことがgRPCサーバでも実現できる。

Server Reflection Tutorial

gRPC Server Reflection Tutorial
https://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md

grpc_cliのビルド

サーバ側のServer Reflection情報を確認するためのクライアントツールを用意する。実装はc++のみ提供されているようだ。grpc/grpcリポジトリを取得してクライアントツールをビルドする。

$ git clone https://github.com/grpc/grpc
$ cd grpc
$ make grpc_cli

サーバーリフレクションのチュートリアルにはこれしか書かれていないが、依存ライブラリがあるのでそちらのインストールもする。
自分の場合はMacOSなので以下を行ったあとビルドできた。

$ git submodule update --init
$ brew install autoconf automake libtool shtool
$ brew install gflags

もし動かなかったり、他のOS環境の場合は、make run_dep_checksコマンドでビルド環境が整っているか確認する。または、以下のページで他に依存しているものが無いか確認する。

https://github.com/grpc/grpc/blob/master/INSTALL.md

サーバーに対してgprc_cliを使ってみる

grpc_cliのビルドが終わったりgoogle.golang.org/grpcリポジトリで、サンプルのhelloworldサーバーを立ち上げておく。

$ go run examples/helloworld/greeter_server/main.go

helloworldサーバーはgit cloneした直後でも、reflection.Registerが既に呼ばれている。(以下の実行結果はクイックスタートのチュートリアルを行ったあとのサーバのコードなので、SayHelloAgainメソッドが追加されている)

s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
// Register reflection service on gRPC server.
reflection.Register(s)

あとは立ち上げたサーバーに向けてgrpc_cli lsコマンドを実行すると、プロトコルバッファーが取得できる。

./bins/opt/grpc_cli ls localhost:50051 -l
filename: helloworld.proto
package: helloworld;
service Greeter {
  rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
  rpc SayHelloAgain(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
}

filename: grpc_reflection_v1alpha/reflection.proto
package: grpc.reflection.v1alpha;
service ServerReflection {
  rpc ServerReflectionInfo(stream grpc.reflection.v1alpha.ServerReflectionRequest) returns (stream grpc.reflection.v1alpha.ServerReflectionResponse) {}
}

callオプションでメソッドを実行させることもできた。

$ ./bins/opt/grpc_cli call localhost:50051 SayHelloAgain "name: 'gRPC CLI'"
connecting to localhost:50051
message: "Hello again gRPC CLI"

Rpc succeeded with OK status

チュートリアルを終えて

reflectionパッケージにはRegisterメソッドしかない。

https://godoc.org/google.golang.org/grpc/reflection

現状Goのコードで直接リフレクションデータを取得できるようにはなっていないっぽいが、grpc_reflection_v1alphaにリフレクション結果の構造体定義がもろもろされている(grpc_cli lsコマンドの結果にも含まれている)。後々Goのコードからでも扱えるようになるのかな?

https://godoc.org/google.golang.org/grpc/reflection/grpc_reflection_v1alpha

grpc_cliのコマンドのusageでオプションを見ると、もろもろの認証情報も付加できるようなので、本番用に構築したgRPCサーバでも利用できそう。

./bins/opt/grpc_cli ls

Wrong number of arguments for ls

List services
  grpc_cli ls <address> [<service>[/<method>]]
    <address>                ; host:port
    <service>                ; Exported service name
    <method>                 ; Method name
    --l                      ; Use a long listing format
    --outfile                ; Output filename (defaults to stdout)
    --enable_ssl             ; Set whether to use tls
    --use_auth               ; Set whether to create default google credentials
    --access_token           ; Set the access token in metadata, overrides --use_auth

参考URL

GRPC Server Reflection Protocol
https://github.com/grpc/grpc/blob/master/doc/server-reflection.md

gRPC Server Reflection Tutorial
https://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md

GoDoc:google.golang.org/grpc/reflection
https://godoc.org/google.golang.org/grpc/reflection

GoDoc:google.golang.org/grpc/reflection/grpc_reflection_v1alpha
https://godoc.org/google.golang.org/grpc/reflection/grpc_reflection_v1alpha

gRPC Service discovery with Server Reflection and gRPC CLI in Go
https://www.goheroe.org/2017/08/19/grpc-service-discovery-with-server-reflection-and-grpc-cli-in-go/

gRPC関連の記事