会社の業務でgRPC触ることがあったのですが、そもそもRPCってなんぞやって状態でしたので、勉強してみることにしました。
まずgRPCを勉強しようと思った時に、不明な用語があったのでそれらを整理してから進めることにしました。
RPCとは
まずRPCは、Remote Procedure Call(遠隔手続き呼び出し)の略で、プログラムから別のアドレス空間にあるサブルーチンや手続きを実行することを可能にする技術のこと。
でgRPCは、Google社内で使われていたRPCフレームワークがOSS化され、gRPCと名前がついたもののことだそうです。 ちなみにgRPCのgはGoogleのgではないです。バージョン毎にいろいろg縛りの言葉がついてるようです。 ここに書いてた GRPC Core: g_stands_for
Protocol Buffersとは
gRPCはデータをProtocol Buffersにシリアライズしてやりとりを行う。 Protocol BuffersもGoogleが開発したフォーマットで、XMLとの比較で、3〜10倍小さく、20〜100倍高速であると主張しているとのこと。
ProtocolBuffersは、protoファイルを作成します。 ファイルをコンパイルすると任意の言語用のコードを自動で作成してくれます。 GoやRubyなど様々な言語に対応しています。 現在はproto3です(いつから3なのか、2との違いは何なのかちゃんと調べてない)
試してみる
公式のチュートリアルの通りにやってみる。 まずサンプルをダウンロードし、ディレクトリ移動
$ git clone -b v1.28.1 https://github.com/grpc/grpc $ cd grpc $ cd examples/ruby
サーバーを起動する。
$ ruby greeter_server.rb
別のターミナルでクライアントを起動
$ ruby greeter_client.rb # 結果が帰ってくる "Greeting: Hello world"
どういう仕組みかコードを確認。
まずgreeter_client.rb
# GreeterServer is simple server that implements the Helloworld Greeter server. class GreeterServer < Helloworld::Greeter::Service # say_hello implements the SayHello rpc method. def say_hello(hello_req, _unused_call) Helloworld::HelloReply.new(message: "Hello #{hello_req.name}") end end # main starts an RpcServer that receives requests to GreeterServer at the sample # server port. def main s = GRPC::RpcServer.new s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure) s.handle(GreeterServer) # Runs the server with SIGHUP, SIGINT and SIGQUIT signal handlers to # gracefully shutdown. # User could also choose to run server via call to run_till_terminated s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT']) end
mainでRPCサーバーを0.0.0.0:50051
で起動しハンドラーにGreeterServer
を設定している。
GreeterServer
はsay_hello
というメソッドを持ち、
Helloworld::HelloReply.new(message: "Hello #{hello_req.name}")
(これはhelloworld_services_pb.rbに定義されていた。)
を実行する。
Hello + リクエストのnameプロパティの値を返す
クライアント側
def main stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure) user = ARGV.size > 0 ? ARGV[0] : 'world' message = stub.say_hello(Helloworld::HelloRequest.new(name: user)).message p "Greeting: #{message}" end
gRPCのスタブを生成し、say_helloメソッドに"world"を渡す。 サーバから帰ってきたメッセージにGreetingを付加して出力している。
所感
まずはこんな感じってのがわかった。 クライアントからサーバーのメソッドを呼び出すという概要は理解できた。 チュートリアルの最初の最初をやっただけなので、protoファイルの作り方やストリーミング など、もっと学習していこうと思います。