grpcurlはgRPCサーバに対してcurlのように通信が行えるクライアントツールです。
このように利用できます。
grpcurl 192.168.0.1 helloworld.Greeter/helloworld
この記事ではgrpcurlのインストールから実際に叩いてみるところまでをご紹介します。またこの記事で紹介するコードはいかに格納しています。
前提
- CentOS7の環境であること
- pipがインストールされていること
準備
mkdir ~/grpctest/ cd ~/grpctest
ライブラリのインストール
pip install grpcio-reflection grpcio grpcio-tools
サーバ用のコードの配置
vim greeter_server.py
以下をコピー。
from concurrent import futures import logging import grpc from grpc_reflection.v1alpha import reflection import helloworld_pb2 import helloworld_pb2_grpc class Greeter(helloworld_pb2_grpc.GreeterServicer): def SayHello(self, request, context): return helloworld_pb2.HelloReply(message="Hello, %s!" %request.name) def SayHelloAgain(self, request, context): return helloworld_pb2.HelloReply(message='Hello again, %s!' % request.name) def CalcBMI(self, request, context): height = float(request.height) / 100 weight = float(request.weight) bmi = weight / (height ** 2) return helloworld_pb2.BMIReply(bmi = bmi) def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) SERVICE_NAMES = ( helloworld_pb2.DESCRIPTOR.services_by_name['Greeter'].full_name, reflection.SERVICE_NAME, ) reflection.enable_server_reflection(SERVICE_NAMES, server) server.add_insecure_port('[::]:50051') server.start() server.wait_for_termination() if __name__ == '__main__': logging.basicConfig() serve()
protoファイルの配置
vim helloworld.proto
以下をコピペ
syntax = "proto3"; option java_multiple_files = true; option java_package = "io.grpc.examples.helloworld"; option java_outer_classname = "HelloWorldProto"; option objc_class_prefix = "HLW"; package helloworld; // The greeting service definition. service Greeter { // Sends a greeting rpc CalcBMI (BMIRequest) returns (BMIReply) {} rpc SayHello (HelloRequest) returns (HelloReply) {} rpc SayHelloAgain (HelloRequest) returns (HelloReply) {} } message BMIRequest { int32 height = 1; int32 weight = 2; } message BMIReply { float bmi = 1; } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }
protoファイルからコードの生成
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
ここまで実行するとこのようになります。
[root@master grpctest]# ls -1 greeter_server.py helloworld.proto helloworld_pb2.py helloworld_pb2_grpc.py
grpcurlのインストール
こちらの記事で紹介しています。
grpcサーバーの起動
python greeter_server.py
localhost:50051
でgRPCサーバがListenします。
grpcurlでサーバに疎通確認
別のターミナルを開いてgrpcurl -plaintext localhost:50051 describe
を叩きましょう。
-plaintext
はTLSを使用していない場合に使うオプションです。これがないとFailed to dial target host "localhost:50051": tls: first record does not look like a TLS handshake
と怒られてしまいます。
正しく接続できれば先ほど起動したサーバに定義されているサービスが表示されます。
describeコマンド
登録されているサービスの詳細情報
client# grpcurl -plaintext localhost:50051 describe grpc.reflection.v1alpha.ServerReflection is a service: service ServerReflection { rpc ServerReflectionInfo ( stream .grpc.reflection.v1alpha.ServerReflectionRequest ) returns ( stream .grpc.reflection.v1alpha.ServerReflectionResponse ); } helloworld.Greeter is a service: service Greeter { rpc CalcBMI ( .helloworld.BMIRequest ) returns ( .helloworld.BMIReply ); rpc SayHello ( .helloworld.HelloRequest ) returns ( .helloworld.HelloReply ); rpc SayHelloAgain ( .helloworld.HelloRequest ) returns ( .helloworld.HelloReply ); }
登録されているメソッドの詳細情報
client# grpcurl -plaintext 0.0.0.0:50051 describe helloworld.Greeter.CalcBMIhelloworld.Greeter.CalcBMI is a method: rpc CalcBMI ( .helloworld.BMIRequest ) returns ( .helloworld.BMIReply );
listコマンド
登録されているサービスの一覧
client# grpcurl -plaintext 0.0.0.0:50051 list grpc.reflection.v1alpha.ServerReflection helloworld.Greeter
サービスに含まれるメソッドの一覧
client# grpcurl -plaintext 0.0.0.0:50051 list helloworld.Greeter helloworld.Greeter.CalcBMI helloworld.Greeter.SayHello helloworld.Greeter.SayHelloAgain
メソッドを叩いてみる
SayHelloメソッドの場合
client# grpcurl -plaintext -d '{"name": "taro" }' 0.0.0.0:50051 helloworld.Greeter.SayHello { "message": "Hello, taro!" }
SayHelloAgainメソッドの場合
client# grpcurl -plaintext -d '{"name": "taro" }' 0.0.0.0:50051 helloworld.Greeter.SayHelloAgain { "message": "Hello again, taro!" }
CalcBMIメソッドの場合
client# grpcurl -plaintext -d '{"height": 160, "weight": 60 }' 0.0.0.0:50051 helloworld.Greeter.CalcBMI { "bmi": 23.4375 }
余談ですがcurl
コマンドのようにパスで(helloworld.Greeter/CalcBMI
)アクセスすることができます。
client# grpcurl -plaintext -d '{"height": 160, "weight": 60 }' 0.0.0.0:50051 helloworld.Greeter/CalcBMI { "bmi": 23.4375 }