【メモ】gRPCのクライアントツールpolyglotでサンプルアプリケーションに接続する

2016.10.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。
先月GAを迎えたGoogle製RPCフレームワークgRPCをちまちま触っています。

今回はgRPCサーバーへの接続をデバッグするためのクライアントツールpolyglotの最低限の使い方を、サンプルアプリケーションを実行するgRPCサーバーを使ってご紹介します。

セットアップ

polyglotはJava版gRPCクライアントのCLIツールです。手元のマシンにJREをインストールしリリースページからjarファイルをダウンロード、実行すればOKです。

動作確認環境

  • OS: macOS Sierra
  • Java: バージョン1.8.0_51
  • polyglot: v1.2.0
$ java -jar polyglot.jar --help
[main] INFO me.dinowernli.grpc.polyglot.Main - Polyglot version: 1.2.0
[main] INFO me.dinowernli.grpc.polyglot.Main - Usage:  [--add_protoc_includes <path1>,<path2>] [--command <call|list_services>] [--config_name <config-name>] [--config_set_path <path/to/config.pb.json>] [--deadline_ms <number>] [--endpoint <host>:<port>] [--full_method <some.package.Service/doSomething>] [--help] [--method_filter method_name] [--output_file_path <path>] [--proto_discovery_root <path>] [--service_filter service_name] [--tls_ca_cert_path <path>] [--use_tls true|false] [--with_message true|false]
$

こんな感じに表示されればOKです。なお、自分の環境では環境変数JAVA_HOMEの設定を求められたので、/Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Homeを指定しました。

使い方

gRPCのクライアント/サーバーのインターフェースは、Protocol Bufferバージョン3.protoファイルで定義します。サンプルアプリケーションhelloworld.protoを以下に示します。

helloworld/helloworld.proto

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

gRPCで利用する.protoファイルには、サービス定義とメッセージ定義がそれぞれ記述されます。gRPCのサービスは、rpcがクライアントが呼び出すAPIコール、serviceおよびpackagerpcをグルーピングする上位階層です。rpcのリクエスト、レスポンスをそれぞれmessageを指定します。今回は、12行目のSayHelloをコールしてみたいと思います。

  • リクエストメッセージ: polyglotはJSONリクエストメッセージを標準入力から入力するため、echoコマンドからパイプラインでpolyglotに渡しましょう。今回はHelloRequestメッセージがリクエストになるので、そのプロパティであるnameを指定します。
  • --commandオプション: 通常のリクエストではcallになります。
  • --endpointオプション: gRPCサーバーのホスト名:ポート番号を指定します。
  • --full_methodオプション: <package>.<service>/<rpc>の形式でAPIを指定します。
  • --proto_discovery_rootオプション: .protoファイルを配置しているディレクトリ名を指定します。
  • --use_tlsオプション: TLS接続する場合はtrueを指定(デフォルトはfalse)
  • --tls_ca_cert_pathオプション: TLS接続時のCA証明書を指定 *1

以下のような感じで実行してみます。

$ echo "{'name':'world'}" | java -jar polyglot.jar \
    --command=call \
    --endpoint=grpc.otaki.classmethod.info:50051 \
    --full_method=helloworld.Greeter/SayHello \
    --proto_discovery_root=/Users/ryuta/.go/src/google.golang.org/grpc/examples/helloworld/helloworld/
    --use_tls=true \
    --tls_ca_cert_path=/usr/local/etc/openssl/cert.pem
[main] INFO me.dinowernli.grpc.polyglot.Main - Polyglot version: 1.2.0
[main] INFO me.dinowernli.grpc.polyglot.Main - Loaded configuration: default
[main] INFO me.dinowernli.grpc.polyglot.command.ServiceCall - Creating dynamic grpc client
[main] INFO io.grpc.internal.ManagedChannelImpl - [ManagedChannelImpl@63355449] Created with target grpc.otaki.classmethod.info:50051
[main] INFO me.dinowernli.grpc.polyglot.command.ServiceCall - Making rpc with 1 request(s) to endpoint [grpc.otaki.classmethod.info:50051]
[main] INFO me.dinowernli.grpc.polyglot.grpc.DynamicGrpcClient - Making unary call
[grpc-default-executor-1] INFO me.dinowernli.grpc.polyglot.io.LoggingStatsWriter - Got response message
{
  "message": "Hello world"
}

[grpc-default-executor-1] INFO me.dinowernli.grpc.polyglot.io.LoggingStatsWriter - Completed rpc with 1 response(s)
$

レスポンスがJSON形式で表示されました! なお、オプションは以下のようにコンフィグファイルに記述することもできるので、オプション数を減らすために利用しても良いでしょう。

~/.polyglot/config.pb.json

{
  "configurations": [
    {
      "name": "default",
      "call_config": {
        "use_tls": "true",
				"tls_ca_cert_path": "/usr/local/etc/openssl/cert.pem"
      }
    }
  ]
}

まとめ

gRPCのクライアントツール、polyglotの基本的な使い方をご紹介しました。Streamingのときはどうなるかなど、まだ気になる点がいろいろあるので、引き続き調べてみたいと思います。

脚注

  1. 今回はpolyglot既定のCA証明書がLet's Encryptに対応していなかったためHomebrewのOpenSSLのCA証明書を指定