何
高性能、クロス言語、クロスプラットフォームの RPC フレームワークです
なぜ
アドバンテージ
-
protobuf バイナリ メッセージ、優れたパフォーマンス/高効率 (優れたスペースと時間の効率)
-
GRPC は protobuf を通じてインターフェイスを定義できるため、より厳格なインターフェイス制約を設けることができます。
欠点がある
-
GRPC は接続プールを提供していないため、独自に実装する必要があります
-
「サービスディスカバリ」および「ロードバランシング」メカニズムは提供されていません
-
Protobuf バイナリの可読性が低い
どうやって
-
依存関係を追加する
-
https://github.com/grpc/grpc-java/blob/master/README.md
-
-
pbファイルを定義する
-
-
プラグインを通じて Java ファイルを生成する
ソースコード分析
全体的なアーキテクチャ
サービス登録 (レジストリ パック) は、メソッド呼び出しモジュールによるクエリ用にサービスの説明、インターフェイスの説明、およびその他の情報を登録する役割を果たします。
メソッド呼び出し (Call Pack) は実際のメソッド呼び出しロジックであり、最終的には実装したサービス インターフェイスに対応するメソッドを呼び出します。
ネットワーク ストリーム (ストリーム パック) は、メソッド呼び出しのネットワーク セッションをカプセル化したものです。つまり、メソッド呼び出しはストリームです。
送信ロジック (トランスポート パック) は、実際の基礎となる IO データ送信と対応するイベント リスナーの構築を担当します。
サービス管理 (Server Pack) は、論理サービス ServerImpl と監視サービス NettyServer の構築と起動を担当します。これはサーバー ロジック全体の関数ファクトリです。
サービス呼び出しの原則
サービスコール方法
-
一般的な RPC 呼び出しモード、つまり要求/応答モード。
-
HTTP/2.0に基づくストリーミング呼び出し方式。
通常のコール - 同期ブロッキングコール
コード
BlockingStub = GreeterGrpc.newBlockingStub(チャネル);
...
HelloRequest リクエスト = HelloRequest.newBuilder().setName(name).build();
HelloReply 応答。
試す {
応答 = ブロッキングStub.sayHello(リクエスト);
...
原理
同期サービス コールは、フレームワーク層で gRPC フレームワークの ClientCalls によってカプセル化されます。サービス コールが非同期的に開始された後、呼び出し元のスレッドは、応答が受信されるまで同期的にブロックされ、その後、ブロックされたビジネス スレッドが起動されます。
将来ベースの非同期 RPC 呼び出し
コード
HelloRequest リクエスト = HelloRequest.newBuilder().setName(name).build();
試す {
com.google.common.util.concurrent.ListenableFuture<io.grpc.examples.helloworld.HelloReply>
listenableFuture = futureStub.sayHello(リクエスト);
Futures.addCallback(listenableFuture, new FutureCallback<HelloReply>() {
@オーバーライド
public void onSuccess(@Nullable HelloReply 結果) {
logger.info("挨拶: " + result.getMessage());
}
原理
ListenableFuture を gRPC の Future リストに追加し、新しい FutureCallback オブジェクトを作成します。ListenableFuture が応答を取得すると、gRPC の DirectExecutor スレッド プールは新しく作成された FutureCallback を呼び出して onSuccess または onFailure を実行し、非同期コールバック通知を実装します。
リアクティブ スタイルの非同期 RPC 呼び出し
コード
HelloRequest リクエスト = HelloRequest.newBuilder().setName(name).build();
io.grpc.stub.StreamObserver<io.grpc.examples.helloworld.HelloReply> responseObserver =
新しい io.grpc.stub.StreamObserver<io.grpc.examples.helloworld.HelloReply>()
{
public void onNext(HelloReply 値)
{
logger.info("挨拶: " + value.getMessage());
}
public void onError(Throwable t){
logger.warning(t.getMessage());
}
public void onCompleted(){}
};
stub.sayHello(request,responseObserver);
原理
応答 StreamObserver を入力パラメーターとして非同期サービス呼び出しに渡すと、メソッドは空を返し、プログラムは現在のビジネス スレッドをブロックせずに下方向に実行を続けます。
ストリーミングモードサービスコール
-
サーバーストリーミング
-
クライアントストリーミング
-
サーバーとクライアント間の双方向ストリーミング
サーバーストリーミング
コード
rpc ListFeature(Rectangle) は (ストリーム機能) {} を返します
public void listFeature(io.grpc.examples.routeguide.Rectangle request,
io.grpc.stub.StreamObserver<io.grpc.examples.routeguide.Feature> responseObserver) {
asyncUnimplementedUnaryCall(METHOD_LIST_FEATURES、responseObserver);
}
原理
io.grpc.stub.StreamObserver responseObserver を構築し、その 3 つのコールバック インターフェイスを実装します。これはサーバー側ストリーミング モードであるため、その onNext(Feature value) が複数回コールバックされ、それぞれが応答を表すことに注意してください。返されると、onCompleted() メソッドが呼び出されます。
クライアントストリーミング
コード
rpc RecordRoute(stream Point) は (Routesummary) {} を返します
StreamObserver<Point> requestObserver = asyncStub.recordRoute(responseObserver);
試す {
// 特徴リストからランダムに選択された numPoints ポイントを送信します。
for (int i = 0; i < numPoints; ++i) {
int インデックス = ランダム.nextInt(features.size());
ポイント point = features.get(index).getLocation();
info("訪問ポイント {0}, {1}", RouteGuideUtil.getLatitude(point),
RouteGuideUtil.getLongitude(point));
requestObserver.onNext(ポイント);
原理
非同期サービス呼び出しは、リクエスト StreamObserver オブジェクトを取得し、ループ内で requestObserver.onNext(point) を呼び出し、リクエスト メッセージをサーバーに非同期に送信します。送信が完了したら、requestObserver.onCompleted() を呼び出して、すべてのリクエストがサーバーに通知されます。が送信され、サーバーからの応答を受信できるようになります。
双方向ストリーミング
コード
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
StreamObserver<RouteNote> requestObserver =
asyncStub.routeChat(new StreamObserver<RouteNote>() {
@オーバーライド
public void onNext(RouteNote note) {
info("{1}、{2} でメッセージ \"{0}\" を受信しました", note.getMessage(), note.getLocation()
.getLatitude()、note.getLocation().getLongitude());
if (testHelper != null) {
testHelper.onMessage(note);
}
}
//複数のリクエストを送信する
for (RouteNote リクエスト : リクエスト) {
info("メッセージ \"{0}\" を {1}、{2} に送信中", request.getMessage(), request.getLocation()
.getLatitude()、request.getLocation().getLongitude());
requestObserver.onNext(リクエスト);
}
} catch (RuntimeException e) {
// RPCをキャンセルする
requestObserver.onError(e);
eを投げます。
}
// リクエストの終了をマークします
requestObserver.onCompleted();
原理
ストリーミング応答オブジェクト StreamObserver を構築し、onNext などのインターフェイスを実装します。サーバーもストリーミング モードであるため、複数の応答があり、onNext が複数回呼び出されることになります。
ループ内で requestObserver の onNext メソッドを呼び出してリクエスト メッセージを送信します。