gRPCの紹介
ここでは、gRPCとプロトコルバッファについてまとめる。gRPCはそのインターフェース定義言語(IDL)とメッセージ交換フォーマットの基礎としてプロトコルバッファを使用することができる。
概要
gRPCでは、クライアントアプリケーションが別のマシンにあるサーバーアプリケーションのメソッドをローカルオブジェクトのように直接呼び出せるので、分散アプリケーションサービスを容易に作成することができる。
例えば上記の図を考える。Rubyでクライアントサイドのアプリケーションを実装しており、C++サーバーで認証機能などを実装しているとする。gRPCを使わない場合は、C++サーバーにユーザーのID、パスワードといったデータが格納されているJSONデータを渡し、C++の方で認証を行う方式が取られる。
しかし、gRPCで行えば、わざわざJSON形式にフォーマットを変えてC++サーバーにリクエストするコードを書く必要はなく、あたかも同じサーバーにあるかのようにメソッドを呼び出すだけで背後でC++サーバーとやり取りができる仕組みである。
プロトコルバッファーの操作
デフォルトでは、gRPCは構造化データをシリアライズするためのGoogleの成熟したオープンソースであるProtocol Buffersを使用する(JSONなどの他のデータ形式でも使用可能)。
プロトコルバッファはJSONやCSVなどのようなデータ形式の一種である。
プロトコルバッファを扱う最初のステップとして、シリアライズしたいデータの構造をprotoファイルに定義すること。これは.protoという拡張子を持つ通常のテキストファイルである。プロトコルバッファのでーたはメッセージ
として構造化されており、各メッセージはフィールド
と呼ばれる一連の名前と値のペアを含む情報の小さな論理的な記録である
message Person {
string name = 1;
int32 id = 2;
bool has_ponycopter = 3;
}
一旦データ構造を指定したら、プロトコルバッファコンパイラのprotocを使って、protoの定義から好きな言語でデータアクセスクラスを生成する。これらはname()やset_name()のような各フィールドの簡単なアクセサと構造体全体を生のバイトからシリアライズ・パースするメソッドを提供する。
例えば、C++の場合を考える。上記のprotoファイルに対してprotocを使ってコンパイルをするとPersonというクラスが生成される。このクラスをアプリケーションで使用すると、Personプロトコル・バッファ・メッセージの入力、シリアライズ、取得を行うことができる。
上記のprotoファイルをコンパイルした結果が以下の通り
https://gist.github.com/Macho000/dee8a31da0ef6e9335768a113ce19507
gRPCのサービス一覧
4種類のサービスメソッドを定義することができる。
- 単一RPC
- クライアントがサーバーに1つのりクエウトを送り、通常の関数呼び出しと同じように1つのレスポンスを返す
rpc SayHello(HelloRequest) returns (HelloResponse);
- サーバーストリーミングRPC
- クライアントがサーバにリクエストを送信し、一連のメッセージを読み取るためのストリームを取得する
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
- クライアントストリーミングRPC
- クライアントが一連のメッセージを書き、提供されたストリームを使用してサーバーに送信する。クライアントがメッセージの書き込みを終えると、サーバーがメッセージを読み込んで応答を返すのを待つ。
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
- 双方向ストリーミングRPC
- 双方とも読み書き可能なストリームを使用して一連おメッセージを送信する。2つのストリームは独立して動作するため、クライアントとサーバは好きな順序で読み書きができる。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
APIの使用
.proto
ファイルのサービス定義から始まり、gRPCはクライアント側とサーバ側のコードを生成するプロトコルバッファコンパイラプラグインを提供する。gRPCユーザは通常、クライアント側でこれらのAPIを呼び出して、サーバーがわで対応するAPIを実装する
- サーバー側では、サービスが宣言したメソッドを実装し、クラインアントからの呼び出しを処理するためにgRPCサーバーを実行する。gRPCインフラストラクチャは受信したリクエストをデコードし、サービスメソッドを実行し、サービス応答をエンコードする。
- クライアント側ではサービスと同じメソッドを実装したスタブと呼ばれるローカルオブジェクトを用意する。そしてクライアントはローカルオブジェクトのメソッドを呼び出すだけで、呼び出しのパラメータを適切なプロトコルバッファのメッセージタイプにラップする。つまり、ローカルオブジェクトのメソッドを呼び出すことによって、サーバー側のメソッドを呼び出すことができる。
参考文献