コアコンセプト、アーキテクチャ、ライフサイクル

gRPCの主要な概念の紹介、gRPCアーキテクチャとRPCライフサイクルの概要。

コアコンセプト、アーキテクチャ、ライフサイクル

gRPCの主要な概念の紹介、gRPCアーキテクチャとRPCライフサイクルの概要。

gRPCに慣れていないですか? まずはgRPCの紹介をお読みください。言語固有の詳細については、選択した言語のクイックスタート、チュートリアル、およびリファレンスドキュメントを参照してください。

概要

サービス定義

多くのRPCシステムと同様に、gRPCは、サービスを定義し、パラメータと戻り値の型を指定してリモートで呼び出せるメソッドを指定するという考えに基づいています。デフォルトでは、gRPCはインターフェース定義言語(IDL)としてプロトコルバッファを使用し、サービスインターフェースとペイロードメッセージの構造の両方を記述します。必要に応じて他の代替手段を使用することも可能です。

service HelloService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}

gRPCでは、4種類のサービスメソッドを定義できます。

  • クライアントがサーバーに単一のリクエストを送信し、単一のレスポンスを受け取るUnary RPC。通常の関数呼び出しと同様です。

    rpc SayHello(HelloRequest) returns (HelloResponse);
    
  • クライアントがサーバーにリクエストを送信し、メッセージのシーケンスを読み取るためのストリームを受け取るサーバー ストリーミング RPC。クライアントは、メッセージがなくなるまで返されたストリームから読み取ります。gRPCは、個々のRPC呼び出し内でのメッセージ順序を保証します。

    rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
    
  • クライアントがメッセージのシーケンスを書き込み、提供されたストリームを使用してサーバーに送信するクライアント ストリーミング RPC。クライアントがメッセージの書き込みを終了したら、サーバーがそれらを読み取ってレスポンスを返すのを待ちます。ここでもgRPCは、個々のRPC呼び出し内でのメッセージ順序を保証します。

    rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
    
  • 双方向ストリーミング RPCでは、両側が読み書き可能なストリームを使用してメッセージのシーケンスを送信します。2つのストリームは独立して動作するため、クライアントとサーバーは任意の順序で読み書きできます。たとえば、サーバーはクライアントメッセージをすべて受信してからレスポンスを書き込むのを待つことも、メッセージを読み取ってからメッセージを書き込むことを交互に行うことも、その他の読み書きの組み合わせで行うこともできます。各ストリーム内のメッセージの順序は保持されます。

    rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
    

RPCのさまざまな種類については、以下のRPCのライフサイクルセクションで詳しく説明します。

APIの使用

.protoファイルでのサービス定義から開始して、gRPCはプロトコルバッファコンパイラプラグインを提供し、クライアント側およびサーバー側のコードを生成します。gRPCユーザーは通常、クライアント側でこれらのAPIを呼び出し、サーバー側で対応するAPIを実装します。

  • サーバー側では、サーバーはサービスによって宣言されたメソッドを実装し、gRPCサーバーを実行してクライアントの呼び出しを処理します。gRPCインフラストラクチャは、受信リクエストをデコードし、サービスメソッドを実行し、サービスレスポンスをエンコードします。
  • クライアント側では、クライアントにはスタブ(一部の言語ではクライアントという用語が好まれます)として知られるローカルオブジェクトがあり、サービスと同じメソッドを実装しています。クライアントは、ローカルオブジェクト上のこれらのメソッドを呼び出すだけでよく、メソッドはパラメータを適切なプロトコルバッファメッセージタイプにラップし、リクエストをサーバーに送信し、サーバーのプロトコルバッファレスポンスを返します。

同期 vs 非同期

レスポンスがサーバーから到着するまでブロックする同期RPC呼び出しは、RPCが目指す手続き呼び出しの抽象化に最も近いものです。一方で、ネットワークは本質的に非同期であり、多くのシナリオでは、現在のスレッドをブロックせずにRPCを開始できることが役立ちます。

ほとんどの言語でのgRPCプログラミングAPIには、同期と非同期の両方のフレーバーがあります。各言語のチュートリアルおよびリファレンスドキュメントで詳細を確認できます(完全なリファレンスドキュメントは近日公開予定です)。

RPCのライフサイクル

このセクションでは、gRPCクライアントがgRPCサーバーメソッドを呼び出したときに何が起こるかを詳しく見ていきます。完全な実装については、言語固有のページを参照してください。

Unary RPC

まず、クライアントが単一のリクエストを送信し、単一のレスポンスを受け取る最も単純な種類のRPCを検討します。

  1. クライアントがスタブメソッドを呼び出すと、サーバーは、RPCがクライアントのメタデータとともに呼び出されたこと、メソッド名、および適用可能な場合は指定されたデッドラインを通知されます。
  2. サーバーは、独自の初期メタデータ(レスポンスの前に送信する必要がある)をすぐに送信するか、クライアントのリクエストメッセージを待つことができます。どちらが先に発生するかは、アプリケーション固有です。
  3. サーバーがクライアントのリクエストメッセージを受け取ると、レスポンスを作成および移入するために必要な作業を実行します。レスポンスは、(成功した場合)ステータス詳細(ステータスコードとオプションのステータスメッセージ)およびオプションのトレーリングメタデータとともにクライアントに返されます。
  4. レスポンスステータスがOKの場合、クライアントはレスポンスを受け取り、クライアント側での呼び出しが完了します。

サーバー ストリーミング RPC

サーバー ストリーミング RPCはUnary RPCに似ていますが、サーバーがクライアントのリクエストに対するレスポンスとしてメッセージのストリームを返す点が異なります。すべてのメッセージを送信した後、サーバーのステータス詳細(ステータスコードとオプションのステータスメッセージ)およびオプションのトレーリングメタデータがクライアントに送信されます。これにより、サーバー側の処理が完了します。クライアントは、サーバーのすべてのメッセージを受け取ると完了します。

クライアント ストリーミング RPC

クライアント ストリーミング RPCはUnary RPCに似ていますが、クライアントが単一のメッセージではなくメッセージのストリームをサーバーに送信する点が異なります。サーバーは、通常、クライアントのすべてのメッセージを受信した後、単一のメッセージ(ステータス詳細とオプションのトレーリングメタデータとともに)で応答します。

双方向ストリーミング RPC

双方向ストリーミング RPCでは、呼び出しは、クライアントがメソッドを呼び出し、サーバーがクライアントメタデータ、メソッド名、およびデッドラインを受け取ることから開始されます。サーバーは、初期メタデータを返すか、クライアントがメッセージのストリーミングを開始するのを待つかを選択できます。

クライアント側とサーバー側のストリーム処理はアプリケーション固有です。2つのストリームは独立しているため、クライアントとサーバーは任意の順序でメッセージを読み書きできます。たとえば、サーバーはクライアントのメッセージをすべて受信してからメッセージを書き込むのを待つことも、サーバーとクライアントが「ピンポン」をプレイすることもできます。サーバーはリクエストを受け取り、レスポンスを返し、クライアントはレスポンスに基づいて別のリクエストを送信するという具合です。

デッドライン/タイムアウト

gRPCでは、クライアントはRPCが完了するのを待つことができる時間を指定でき、それより長い場合はRPCがDEADLINE_EXCEEDEDエラーで終了します。サーバー側では、サーバーは特定のRPCがタイムアウトしたかどうか、またはRPCを完了するために残された時間をクエリできます。

デッドラインまたはタイムアウトの指定は言語固有です。一部の言語APIはタイムアウト(時間の経過)に基づいて動作し、一部の言語APIはデッドライン(特定時点)に基づいて動作し、デフォルトのデッドラインがある場合とない場合があります。

RPCの終了

gRPCでは、クライアントとサーバーの両方が呼び出しの成功を独立してローカルに判断し、その結論は一致しない場合があります。これは、たとえば、サーバー側で正常に完了したRPC(「すべてのレスポンスを送信しました!」)があっても、クライアント側で失敗する(「レスポンスがデッドライン後に到着しました!」)可能性があることを意味します。サーバーがクライアントがすべてのリクエストを送信する前に完了することを決定することも可能です。

RPCのキャンセル

クライアントまたはサーバーは、いつでもRPCをキャンセルできます。キャンセルはRPCを直ちに終了するため、それ以上の処理は行われません。

メタデータ

メタデータは、特定のRPC呼び出しに関する情報(認証の詳細など)であり、キーと値のペアのリストの形式をとります。キーは文字列で、値は通常文字列ですが、バイナリデータにすることもできます。

キーは大文字小文字を区別せず、ASCII文字、数字、および特殊文字-_.で構成され、grpc-(gRPC自体が予約している)で始まってはなりません。バイナリ値のキーは-binで終わり、ASCII値のキーはそうではありません。

ユーザー定義メタデータはgRPCでは使用されません。これにより、クライアントは呼び出しに関連付けられた情報をサーバーに提供したり、その逆を行ったりできます。

メタデータへのアクセスは言語に依存します。

チャンネル

gRPCチャンネルは、指定されたホストとポートにあるgRPCサーバーへの接続を提供します。クライアントスタブを作成する際に使用されます。クライアントは、メッセージ圧縮のオン/オフなどのgRPCのデフォルトの動作を変更するために、チャンネル引数を指定できます。チャンネルにはconnectedidleなどの状態があります。

チャンネルを閉じる際のgRPCの処理は言語に依存します。一部の言語では、チャンネルの状態をクエリすることも可能です。