gRPC
-
分散アプリケーションを作成する文脈で役に立つ
-
クライアント・アプリケーションが、あたかもローカル・オブジェクトであるかのように、別のマシンにあるサーバ・アプリケーションのメソッドを直接呼び出すことができる
-
gRPCサービスはプロトコル・バッファをインタフェース定義言語 (IDL) として使用する
-
protocを使って、プロト定義から好みの言語のデータ・アクセス・クラスを生成できる
nodejsのサンプルをcloneして簡単に試せる。
hello world
サーバとクライアントの「スタブ」の両方が、クライアントからHelloRequestパラメータを受け取り、サーバからHelloReplyを返すSayHello RPCメソッドを持っている
ここでいう「スタブ」がなんのことかはっきりわかってないけど
とりあえず、serverファイルとclientファイルが、同じhelloworld.protoを読み込んでる
helloworld.proto
指示通りhello againを追加してみて、protoの定義とserverとclientからの呼び出しのイメージを掴む
- gRPC はリモートから呼び 出されるメソッドとそのパラメータと戻り値の型を指定し、サービ スを定義するという考え方
- gRPCでは、以下の4種類のサービスメソッドを定義することができる
- 単一のレスポンスを返す単項RPC
rpc SayHello(HelloRequest) returns (HelloResponse);
- サーバ・ストリーミング RPC
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
- クライアント・ストリーミングRPC
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
- 双方向ストリーミング RPC
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
- 単一のレスポンスを返す単項RPC
各違いはこの記事の図が超わかりやすい
- サーバーはサービスによって宣言されたメソッドを実装
- gRPCインフラストラクチャは、入ってくるリクエストをデコードし、サービスメソッドを実行し、サービス応答をエンコードする
- クライアントは、サービスと同じメソッドを実装したスタブと呼ばれるローカルオブジェクトを持つ
- クライアントはローカルオブジェクトのメソッドにパラメータを渡して呼び出すだけ
- パラメータを適切なプロトコルバッファのメッセージタイプでラップし、リクエストをサーバーに送信し、サーバーのプロトコルバッファの応答を返す
- クライアントはローカルオブジェクトのメソッドにパラメータを渡して呼び出すだけ
- その他
- サーバ側では成功裏に終了した RPC(「すべての応答を送信した! 」)が、クライアント側では失敗した RPC(「応答が期限を過ぎて到着した! 」)があり得る
- クライアントもサーバーも、いつでもRPCをキャンセルすることができる。ただし、キャンセル前の変更はロールバックはされない
- metadataとchannelsはよくわからん
var PROTO_PATH = __dirname + '/../../protos/route_guide.proto';
var grpc = require('@grpc/grpc-js');
var protoLoader = require('@grpc/proto-loader');
// Suggested options for similarity to existing grpc.load behavior
var packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
var protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
// The protoDescriptor object has the full package hierarchy
var routeguide = protoDescriptor.routeguide;
これを行うと、スタブのコンストラクタはrouteguide名前空間(protoDescriptor.routeguide.RouteGuide)にあり、serice記述子(サーバーを作成するために使用される)はスタブのプロパティ(protoDescriptor.routeguide.RouteGuide.service)になります。
よくわからん
とりあえず、下記のtutorialの通りにRouteGuideの方も実行してみた。
4種類のサービスメソッドそれぞれを実行できたわけだけど、で?って感じ。。
どのような通信なのかのイメージが掴めない
やってみる
これはなんとなくイメージできてたけど
わかりやすく言語化されてるのでメモ
「そのAPIが提供したいサービスをProcedureとしてサーバー上に実装して、それをAPIを使う側であるクライアントコードから直接呼び出すようにする」という発想がRPC(Remote Procedure Call)
これまたわかりやすい
通信方式として、HTTP2を使用。
そこに渡す、引数と戻り値の情報を、Protocol Buffersというシリアライズ方式で変換する
protobufで使用できるデータ型
上記組み込みの型以外に、Googleが定義して公開している便利型「Well Known Types」がある
grpc公式のQuick startに書いてある下記手順をやっとかないと、protocのコード自動生成で怒られるよ
go install google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
以下をzshrcに追記
export PATH="$PATH:$(go env GOPATH)/bin"
gRPCクライアントを実装せずとも
server refrectionをgRPCサーバーに設定したうえで、grpcurlを使えば、grpcメソッドを直接実行できるんだな
server refrectionは、protoに定義されているシリアライズのルールをgRPCサーバーから取得するための機能
gRPCクライアントはprotocコマンドで自動生成されているけどgrpcurlはそうではない
引数をencodeして実行し戻り値をdecodeして読むために知る必要がある
hello_grpc.pb.go(server側)に自動生成されていること
- serverのインターフェース
- server上でgrpc clientを起動する関数
- リクエストを送るクライアントを作るコンストラクタ関数
- クライアントが呼び出せるメソッド一覧をインターフェースで定義
4パターンのメソッドを一通り試せた
双方向ストリーミングを実装して動いてるの見るの嬉しいな
gRPCの場合は「メソッドの呼び出しに成功した場合には、中で何が起ころうともHTTPレスポンスステータスコードは200 OKを返す」
- gRPCは「メソッドを呼び出し、戻り値を受け取る」ことに関心をおいている
- 「gRPCがHTTP/2の上に実装されている」という事実を意識しなくて良いように設計されている
- 「呼び出されたメソッドが正しく処理を実行したか」を知るためにHTTPのステータスコードを見にいくというのはgRPC-likeではない
httpのpackageのdoc
grpcのpackageのdoc