gRPCの仕組み — 遠くの「こんにちは」を呼び出すまで
契約を決めて、挨拶を頼む
まず、呼び出しの契約を見る
「ひよこ」と送ると「こんにちは、ひよこ」と返す単項RPCを考えます。次は hello.proto の例です。
syntax = "proto3";
package hello;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest { string name = 1; }
message HelloReply { string message = 1; }
SayHello が遠隔呼び出しの入口、HelloRequest と HelloReply が送受信するメッセージの型です。1 は文字数や配列番号ではなく、フィールドの識別番号です。このファイルだけで挨拶の処理が動くわけではありません。
契約から、実装と呼び出しへ
Pythonなら独立した仮想環境に grpcio と grpcio-tools を追加し、生成します。
python -m pip install grpcio grpcio-tools
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. hello.proto
メッセージのコードとRPC用のコードができます。次にサーバー側で SayHello の処理を実装し、クライアント側ではChannelとStubを作って呼びます。起動から実行までを試す場合は、公式Pythonクイックスタートのサーバー・クライアントを使ってください。
このページのコードは契約と生成の入口です。通信先のアドレス、ポート、TLS設定、期限を確認してから実際のサーバーへ接続します。
4種類の通信を、回数で見分ける
| パターン | 要求 | 応答 | イメージ |
|---|---|---|---|
| Unary | 1メッセージ | 1メッセージ | 挨拶を一つ頼む |
| Server streaming | 1 | 複数 | 検索結果を順に受け取る |
| Client streaming | 複数 | 1 | 測定値を送り集計を受け取る |
| Bidirectional streaming | 複数 | 複数 | 互いにメッセージを送る |
一つのストリーム内のメッセージ順は保たれます。双方向の二つの流れは独立しており、要求と応答が必ず一対一で交互になるわけではありません。
もう少し詳しく:期限と互換性
期限を設定して、待ち続ける呼び出しを避けます。標準では期限が設定されていない場合があるため、言語のAPIで指定方法を確認します。失敗した書き込みの再試行は、二重実行を避ける設計も必要です。
削除したprotobufのフィールド番号や名前は reserved にし、別の意味で再利用しないようにします。生成コードは業務ルールの正しさまで保証しません。
gRPCは型を共有したサービス間通信やストリーミングの候補です。ブラウザー対応、調査用ツール、運用、相手の対応方式も含めてRESTとの比較で選びましょう。
ペンギン先生のまとめ
「gRPC」って出てきたら「契約を決めて、遠くの処理を関数のように呼ぶ方法」と思えばだいたいOK! 通信なので、結果だけでなく期限と失敗も受け取るよ。
参考資料
-
gRPC:Core concepts — サービス・4種類のRPC・ライフサイクル
-
gRPC:Python Quick start — 生成とサーバー/クライアント
-
gRPC:Deadlines — 期限とキャンセル
-
Protocol Buffers:proto3 — 番号・予約と互換性
-
gRPC HTTP/2 protocol — 通信形式とタイムアウト。