ASP.NETコア3.0 gRPC双方向の流れ

ディレクトリ

I.はじめに

前の記事「ASP.NET 3.0のコア使用gRPCは」の機能がgRPCで、双方向のフロー制御サポートのgRPCはのための非常に強いです、リアルタイムのプッシュメッセージングをサポートし、通話のgRPCサポート双方向の流れの中で言及されました。

II。gRPCストリームは何ですか

シンプルなRPC(単項RPC)、ストリーミングサーバのRPC(サーバーストリーミングRPC)、クライアントストリーミングRPC(クライアントストリーミングRPC)、双方向ストリーミングRPC(双方向ストリーミングRPC):gRPC、すなわち、サービス、の4種類があります。 。彼らは主に次のような特徴があります:

サービスの種類 機能
シンプルなRPC 一般的なRPC呼び出し、リクエストオブジェクトを渡し、戻りオブジェクトを返します。
RPCサーバーストリーミング 要求オブジェクトを渡し、サーバは、結果の複数のオブジェクトを返すことができます
ストリーミングクライアントRPC 複数の着信クライアントがオブジェクトを要求し、サーバは、結果オブジェクトを返します。
双方向フローRPC ストリーミングクライアントとサーバーのRPCのRPCの流れをバインド、あなたは結果オブジェクトが複数返され、リクエストオブジェクトを複数渡すことができます

III。なぜgRPCサポートストリーミング

gRPC通信は、HTTP / 2ストリームへの双方向の流れを達成するために、HTTP / 2に基づいています。多重化HTTP / 2であるために、ストリームの流れの概念を持つHTTP / 2。ビジネス;双方向シリアルストリームは、HTTP / 2接続を介してデータフレームを交換するための独立したサーバやクライアントであり、それはより完全な対話処理論理ユニット、完全なリソース要求、応答データ交換処理のすなわち表現として見ることができます処理は、ストリーム内で完結処理のために生活のストリーム終わりを意味しています。

次のような機能は次のとおりです。

  • HTTP / 2接続は同時にいずれかのエンドポイントスイッチフレーム、オープンフローの複数を保持することができます
  • ストリームは、単独で、または共有のクライアントまたはサーバの作成と使用を使用することができます
  • ストリームは、どちらかの端で閉鎖することができます
  • データストリーム順に送受信されます
  • ストリーム識別子は自然数を表し、1 ^ 31-1間隔2に、端末は、流量分布を作成しなければなりません
  • 流れの間に論理的に並行して、の存在とは無関係

撮影したHTTP / 2マルチプレクサと彼の同類ノートニエヨンジュンによって

四.gRPCは、通話の双方向のフローを使用します

私たちは、その後、ストリーミングサーバ、単純です我々はRPCとRPCの簡単な双方向の流れを持っている場合、第二のセクションに記載されているサービスの4種類に応じて、コールフロー、双方向の流れについて次の直接話が含まれていない前述のRPCのRPCで書きますRPCとRPCクライアントの流れが自然に問題ありません。

ここでは、引き続き使用する以前のコードを、目標は、複数の猫に一度お風呂を達成すべきです。

①まず、でLuCat.proto、猫のためのカウント統計を数2 RPCを定義し、双方向の流れRPC BathTheCatは猫を入浴するために使用しました

syntax = "proto3";

option csharp_namespace = "AspNetCoregRpcService";

import "google/protobuf/empty.proto";
package LuCat; //定义包名

//定义服务
service LuCat{
    //定义给猫洗澡双向流rpc
    rpc BathTheCat(stream BathTheCatReq) returns ( stream BathTheCatResp);
    //定义统计猫数量简单rpc
    rpc Count(google.protobuf.Empty) returns (CountCatResult);
}

message SuckingCatResult{
    string message=1;
}
message BathTheCatReq{
    int32 id=1;
}
message BathTheCatResp{
    string message=1;
}
message CountCatResult{
    int32 Count=1;
}

②実装サービスを追加

ここではReSharperの下アムウェイ、非常に便利

private readonly ILogger<LuCatService> _logger;
private static readonly List<string> Cats=new List<string>(){"英短银渐层","英短金渐层","美短","蓝猫","狸花猫","橘猫"};
private static readonly Random Rand=new Random(DateTime.Now.Millisecond);

public LuCatService(ILogger<LuCatService> logger)
{
    _logger = logger;
}

public override async Task BathTheCat(IAsyncStreamReader<BathTheCatReq> requestStream, IServerStreamWriter<BathTheCatResp> responseStream, ServerCallContext context)
{
    var bathQueue=new Queue<int>();
    while (await requestStream.MoveNext())
    {
        //将要洗澡的猫加入队列
        bathQueue.Enqueue(requestStream.Current.Id);

        _logger.LogInformation($"Cat {requestStream.Current.Id} Enqueue.");
    }

    //遍历队列开始洗澡
    while (bathQueue.TryDequeue(out var catId))
    {
        await responseStream.WriteAsync(new BathTheCatResp() { Message = $"铲屎的成功给一只{Cats[catId]}洗了澡!" });

        await Task.Delay(500);//此处主要是为了方便客户端能看出流调用的效果
    }
}

public override Task<CountCatResult> Count(Empty request, ServerCallContext context)
{
    return Task.FromResult(new CountCatResult()
    {
        Count = Cats.Count
    });
}

BathTheCat方法は、クライアントから送信されたCATIDを複数受信し、キューに追加、などは、クライアント順次浴から送信され、クライアントに返されました。

③クライアントの実装

同上猫ランダムサーバーへの送信10、および、結果バス10を受け取ります。

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var catClient = new LuCat.LuCatClient(channel);
//获取猫总数
var catCount = await catClient.CountAsync(new Empty());
Console.WriteLine($"一共{catCount.Count}只猫。");
var rand = new Random(DateTime.Now.Millisecond);

var bathCat = catClient.BathTheCat();
//定义接收吸猫响应逻辑
var bathCatRespTask = Task.Run(async() =>
{
    await foreach (var resp in bathCat.ResponseStream.ReadAllAsync())
    {
        Console.WriteLine(resp.Message);
    }
});
//随机给10个猫洗澡
for (int i = 0; i < 10; i++)
{
    await bathCat.RequestStream.WriteAsync(new BathTheCatReq() {Id = rand.Next(0, catCount.Count)});
}
//发送完毕
await bathCat.RequestStream.CompleteAsync();
Console.WriteLine("客户端已发送完10个需要洗澡的猫id");
Console.WriteLine("接收洗澡结果:");
//开始接收响应
await bathCatRespTask;

Console.WriteLine("洗澡完毕");

④実行

あなたは、コールの双方向の流れが成功すると、クライアントは、バスリクエストオブジェクト10猫を送信し、サーバは風呂結果オブジェクト10猫を返す見ることができます。そして、通話gRPCの双方向のフローであるリアルタイムのプッシュ、です。

ここでは、ストリーミングクライアントまたはサーバ側のストリーミングコールに進化するために自分自身を向上させることができます。次に、クライアントは、サーバがサーバ呼び出しをストリーミングしている各猫の結果バスを返し、猫IDリストを送信します。順番に、クライアントは、サーバはすべての猫のための入浴時間の結果を返します(猫のすべてのビジネスとして見られるように入浴することは、ビジネスの結果を返します)、猫IDを送信する、クライアントの呼び出しをストリーミングしています。ここで私は発揮しません。

V.フロー制御

gRPCストリーミングのサポートはアクティブ解除の流れを制御するために呼び出すので、フロー制御タイムアウト制限を導出することができます。

我々は対流制御を解除するために使用したものであるCancellationTokenパラメータを渡すことができますストリーミングコール:

1569467990882

私たちは、コードの第四項にあるものを変換:

①クライアント

var cts = new CancellationTokenSource();
//指定在2.5s后进行取消操作
cts.CancelAfter(TimeSpan.FromSeconds(2.5));
var bathCat = catClient.BathTheCat(cancellationToken: cts.Token);
//定义接收吸猫响应逻辑
var bathCatRespTask = Task.Run(async() =>
{
    try
    {
        await foreach (var resp in bathCat.ResponseStream.ReadAllAsync())
        {
            Console.WriteLine(resp.Message);
        }
    }
    catch (RpcException ex) when (ex.StatusCode == StatusCode.Cancelled)
    {
        Console.WriteLine("Stream cancelled.");
    }
});

②サーバー

//遍历队列开始洗澡
while (!context.CancellationToken.IsCancellationRequested && bathQueue.TryDequeue(out var catId))
{
    _logger.LogInformation($"Cat {catId} Dequeue.");
    await responseStream.WriteAsync(new BathTheCatResp() { Message = $"铲屎的成功给一只{Cats[catId]}洗了澡!" });

    await Task.Delay(500);//此处主要是为了方便客户端能看出流调用的效果
}

③実行

双方向のフロー・コール2.5S後に設定した結果を返すコールの最終結果を確認するために、顧客からのトラフィックを削除し、10猫の入浴のすべてを受け取っていない、ストリームが、これは制御gRPCの流れで、キャンセルされました。

VI。終了

ここでは、リアルタイムのプッシュ、サービス・クライアントまたはクライアントからサーバへリアルタイム短プッシュメッセージが、伝統的な意味をプッシュする接続と長いイニシアチブをストリーミング呼び出すことができ、ブロードキャストメッセージは、あなたがサーバー側のストリーミングであるかどうか、同じではありませんクライアント・フローまたは双方向の流れは、クライアントの要求により通信のフローを確立するために、クライアントによって開始されなければなりません。

VII。参考文献

おすすめ

転載: www.cnblogs.com/stulzq/p/11590088.html