zoukankan      html  css  js  c++  java
  • C# 之 Grpc

    1. Grpc 是什么?

    Google RPC A high-performance, open source universal RPC framework

    官方地址:https://www.grpc.io/

    Grpc 开始是由google 开发的,是一款语言中立、平台中立、开源的远程调用(RPC)系统.

    执行流程:

    01.Proto文件

    接口—定义不同语言的实现规范 需要个工具—转换C#代码(webservice代理) 定义了协议接口和数据格式 不同语言—相同文件---等于接口

    类型映射:

    参开地址:https://developers.google.cn/protocol-buffers/docs/proto3#scalar

    序列化支持 PB(Protocol buffer)和 JSON, PB 是一种语言无关的高性能序列化框架,基于 HTTP/2 + PB, 保障了 RPC 调用的高性能。

     02.创建Grpc工程。

    gRPC支持4种流

    1. 简单 RPC(Unary RPC)
    2. 服务端流式 RPC (Server streaming RPC)
    3. 客户端流式 RPC (Client streaming RPC)
    4. 双向流式 RPC(Bi-directional streaming RPC)

     

     1.简单RPC

    syntax = "proto3";
    
    option csharp_namespace = "GrpcDemoClients";
    
    package mathUtilsPackage;
    
    // The greeting service definition.
    service MathUtils {
      // Sends a greeting
      rpc Add (AddRequest) returns (AddReply);
    }
    
    // The request message containing the user's name.
    message AddRequest {
      int32 left = 1;
      int32 right = 2;
    }
    
    // The response message containing the greetings.
    message AddReply {
      int32 total = 1;
    }
    using System.Threading.Tasks;
    using Grpc.Core;
    
    namespace GrpcDemoClients.Services
    {
        public class MathUtilsService:MathUtils.MathUtilsBase
        {
            public override Task<AddReply> Add(AddRequest request, ServerCallContext context)
            {
                return Task.FromResult(new AddReply
                {
                    Total = request.Left + request.Right
                });
            }
        }
    }

    配置对外公开的接口。

    服2.务端配置:

     客户端配置:

     客户端调用:

       private static async Task TestMathTotal()
            {
                using var channel = GrpcChannel.ForAddress(" https://localhost:5001");
                var client = new MathUtils.MathUtilsClient(channel);
                var reply = await client.AddAsync(new AddRequest
                {
                    Left=1,
                    Right=2
                });
                Console.WriteLine("Return the value is:" + reply.Total);
    
            }

    2.服务端流式 RPC  一次请求,多次返回。

    proto 文件:

    syntax = "proto3";
    
    option csharp_namespace = "GrpcDemoClients";
    
    package serverRpcUtilsPackage;
    
    // The greeting service definition.
    service ServerRpcUtils {
      // Sends a greeting
        rpc SelfIncreaseServer(IntArrayModel) returns (stream BathTheCatResp);
    }
    
    message IntArrayModel{
        repeated int32 Numbers=1;//集合
    }
    message BathTheCatResp{
        string Message=1;
    }
    View Code

     server 实现:

    using System;
    using System.Threading.Tasks;
    using Grpc.Core;
    
    namespace GrpcDemoClients.Services
    {
        public class ServerRpcService: ServerRpcUtils.ServerRpcUtilsBase
        {
            public async override Task SelfIncreaseServer(IntArrayModel request, IServerStreamWriter<BathTheCatResp> responseStream, ServerCallContext context)
            {
                foreach (var item in request.Numbers)
                {
                    int number = item;
                    Console.WriteLine($"This is {number} invoke");
                    await responseStream.WriteAsync(new BathTheCatResp() { Message = $"number++ ={++number}!" });
                    await Task.Delay(500);//此处主要是为了方便客户端能看出流调用的效果
                }
            }
        }
    }
    View Code

    调用:

     private static async Task TestServerRpc()
            {
                using var channel = GrpcChannel.ForAddress(" https://localhost:5001");
                var client = new ServerRpcUtils.ServerRpcUtilsClient(channel);
    
                var resp = new IntArrayModel(); 
                for (int i = 0; i < 15; i++)
                {
                    resp.Numbers.Add(i);
                }
    
                var bathCat =  client.SelfIncreaseServer(resp);
    
                var bathCatRespTask = Task.Run(async () =>
                {
                    await foreach (var resp in bathCat.ResponseStream.ReadAllAsync())
                    {
                        Console.WriteLine(resp.Message);
                        Console.WriteLine($"This is  Response {Thread.CurrentThread.ManagedThreadId}");
                        Console.WriteLine("**********************************");
                    }
                });
                Console.WriteLine("客户端已发送完10个id");
                //开始接收响应
                await bathCatRespTask;
    
            }
    View Code

    3.客户端流式 RPC   多次请求,一次性返回。

    proto 文件:

    syntax = "proto3";
    
    option csharp_namespace = "GrpcDemoClients";
    
    package serverRpcUtilsPackage;
    
    // The greeting service definition.
    service ServerRpcUtils {
      // Sends a greeting
        rpc SelfIncreaseServer(IntArrayModel) returns (stream BathTheCatResp);
        rpc SelfIncreaseClient(stream BathTheCatReq) returns (IntArrayModel);
    }
    
    message IntArrayModel{
        repeated int32 Numbers=1;//集合
    }
    message BathTheCatResp{
        string Message=1;
    }
    message BathTheCatReq{
        int32 Id=1;
    }
    View Code

     server 实现:

     public async override Task<IntArrayModel> SelfIncreaseClient(IAsyncStreamReader<BathTheCatReq> requestStream, ServerCallContext context)
            {
                IntArrayModel intArrayModel = new IntArrayModel();
                while (await requestStream.MoveNext())
                {
                    intArrayModel.Numbers.Add(requestStream.Current.Id + 1);
                    Console.WriteLine($"SelfIncreaseClient Number {requestStream.Current.Id} 获取到并处理.");
                    Thread.Sleep(100);
                }
                return intArrayModel;
            }
    View Code

    调用:

     private static async Task TestClientRpc()
            {
                using var channel = GrpcChannel.ForAddress(" https://localhost:5001");
                var client = new ServerRpcUtils.ServerRpcUtilsClient(channel);
                var bathCat = client.SelfIncreaseClient();
                for (int i = 0; i < 10; i++)
                {
                    await bathCat.RequestStream.WriteAsync(new BathTheCatReq() { Id = new Random().Next(0, 20) });
                    await Task.Delay(100);
                    Console.WriteLine($"This is {i} Request {Thread.CurrentThread.ManagedThreadId}");
                }
    
                Console.WriteLine("**********************************");
                //发送完毕
                await bathCat.RequestStream.CompleteAsync();
                Console.WriteLine("客户端已发送完10个id");
                Console.WriteLine("接收结果:");
    
                foreach (var item in bathCat.ResponseAsync.Result.Numbers)
                {
                    Console.WriteLine($"This is {item} Result");
                }
                Console.WriteLine("**********************************");
            }
    View Code

    4.双向流式 RPC  多次请求,多次返回。

     proto 文件:

    rpc SelfIncreaseDouble(stream BathTheCatReq) returns ( stream BathTheCatResp);

     server 实现:

      public async override Task SelfIncreaseDouble(IAsyncStreamReader<BathTheCatReq> requestStream, IServerStreamWriter<BathTheCatResp> responseStream, ServerCallContext context)
            {
    
                while (await requestStream.MoveNext())
                {
                    Console.WriteLine($"SelfIncreaseDouble Number {requestStream.Current.Id} 获取到并处理.");
                    await responseStream.WriteAsync(new BathTheCatResp() { Message = $"number++ ={requestStream.Current.Id + 1}!" });
                    await Task.Delay(500);//此处主要是为了方便客户端能看出流调用的效果
                }
            }
    View Code

    调用:

     private static async Task TestDoubleRpc()
            {
                using var channel = GrpcChannel.ForAddress(" https://localhost:5001");
                var client = new ServerRpcUtils.ServerRpcUtilsClient(channel);
    
                var bathCat = client.SelfIncreaseDouble();
                var bathCatRespTask = Task.Run(async () =>
                {
                    await foreach (var resp in bathCat.ResponseStream.ReadAllAsync())
                    {
                        Console.WriteLine(resp.Message);
                        Console.WriteLine($"This is  Response {Thread.CurrentThread.ManagedThreadId}");
                        Console.WriteLine("**********************************");
                    }
                });
                for (int i = 0; i < 10; i++)
                {
                    await bathCat.RequestStream.WriteAsync(new BathTheCatReq() { Id = new Random().Next(0, 20) });
                    await Task.Delay(100);
                    Console.WriteLine($"This is {i} Request {Thread.CurrentThread.ManagedThreadId}");
                    Console.WriteLine("**********************************");
                }
                //发送完毕
                await bathCat.RequestStream.CompleteAsync();
                Console.WriteLine("客户端已发送完10个id");
                Console.WriteLine("接收结果:");
                //开始接收响应
                await bathCatRespTask;
            }
    View Code

    补充:

    无参数请求

      rpc Count(google.protobuf.Empty) returns (CountResult);//无参数Empty
      public override Task<CountResult> Count(Empty request, ServerCallContext context)
            {
    
                return Task.FromResult(new CountResult()
                {
                    Count = DateTime.Now.Year
                });
            }
    PYTHON
  • 相关阅读:
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    how to use automapper in c#, from cf~
  • 原文地址:https://www.cnblogs.com/delaywu/p/14458675.html
Copyright © 2011-2022 走看看