专栏首页全栈码农画像.NET gRPC核心功能初体验

.NET gRPC核心功能初体验

gRPC是高性能的RPC框架, 有效地用于服务通信(不管是数据中心内部还是跨数据中心)。

由Google开源,目前是一个Cloud Native Computing Foundation(CNCF)孵化项目。

其功能包括:

•双向流•强大的二进制序列化•可插拔的身份验证,负载平衡和运行状况检查

在gRPC中,客户端应用程序可以直接在A服务器上调用B服务器的方法,就好像它是本地对象一样,从而使您更轻松地创建分布式应用程序和微服务。

与许多RPC系统一样,gRPC也是围绕着定义服务的思想(定义可远程调用方法的入参和返回值类型)。

在服务端,服务端实现此接口并运行gRPC服务器,以处理客户端调用。 在客户端,客户端有一个存根,提供与服务器相同的方法。

在本文中,我将向您展示如何使用.NET5创建gRPC服务。我将分解gRPC的一些重要基础概念,并给出一个有意思的包罗核心功能的实例。

1.创建一个gRPC服务器

我们从gRPC服务模板创建一个新的dotnet项目。

如果使用Visual Studio,请创建一个新项目,然后选择gRPC Service模板,使用GrpcAuthor作为项目的名称。

1.1 定义Rpc 服务

客户端与服务端使用protocol buffers交流/通信: protocol buffers既用作服务的接口定义语言(IDL),又用作底层消息交换格式

① 使用protocol buffers在.proto文件中定义服务接口。在其中,定义可远程调用的方法的入参和返回值类型,服务端实现此接口并运行gRPC服务器以处理客户端调用。 ② 定义服务后,使用protocol buffers编译器protoc从.proto文件生成数据访问/传输类,该文件包含服务接口中消息和方法的实现。

关注VS脚手架项目Protos文件夹中的greet.proto。

syntax = "proto3";option csharp_namespace = "GrpcAuthor";package greet;// The greeting service definition.service Greeter {  // Sends a greeting  rpc SayHello (HelloRequest) returns (HelloReply);}// The request message containing the user's name.message HelloRequest {  string name = 1;}// The response message containing the greetings.message HelloReply {  string message = 1;}

从.proto文件内容上大致知道服务功能 (给某人一个回应), 这里提示一些语法:

syntax指示使用的protocol buffers的版本。在这种情况下,proto3是撰写本文时的最新版本。②csharp_namespace指示生成的文件所在的命名空间package说明符也是这个作用,用于防止协议消息类型之间的名称冲突。

对于C#,如果提供选项csharp_namespace,csharp_namespace值将用作命名空间; 在Java中,如果提供选项java_package,java_package将用作包名称。

③service Greeter定义服务基类名称, rpc SayHello (HelloRequest) returns (HelloReply); 是一个一元rpc调用HelloRequestHelloReply是在客户端和服务器之间交换信息的数据结构。它们被称为消息。 你在消息字段中定义的数字是不可重复的,当消息被序列化为Protobuf时,该数字用于标识字段,这是因为序列化一个数字比序列化整个字段名称要快。

1.2 实现服务接口

为了从.proto文件生成代码,可以使用protoc编译器和C#插件来生成服务器或客户端代码。 脚手架项目使用Grpc.AspNetCore NuGet包:所需的类由构建过程自动生成, 你只需要在项目.csproj文件中添加配置节:

<ItemGroup>  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" /></ItemGroup>

生成的代码知道如何使用protocol buffers与其他服务/客户端进行通信。

C#工具生成GreeterBase类型,将用作实现gRPC服务的基类。

public class GreeterService : Greeter.GreeterBase{    private readonly ILogger<GreeterService> _logger;    public GreeterService(ILogger<GreeterService> logger)    {        _logger = logger;    }    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)    {        return Task.FromResult(new HelloReply        {            Message = "Hello " + request.Name        });    }}

最后注册Grpc端点endpoints.MapGrpcService<GreeterService >();

--- 启动服务---...

2. 创建gRPC .NET控制台客户端

Visual Studio创建一个名为GrpcAuthorClient的新控制台项目。

安装如下nuget包: Install-Package Grpc.Net.Client Install-Package Google.Protobuf Install-Package Grpc.Tools

Grpc.Net.Client包含.NET Core客户端; Google.Protobuf包含protobuf消息API; Grpc.Tools对Protobuf文件进行编译。

①拷贝服务端项目中的.proto文件②将选项csharp_namespace值修改为GrpcAuthorClient。③更新.csproj文件的配置节

<ItemGroup>
    <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
  </ItemGroup>

④Client主文件:

static void Main(string[] args)
{
      var serverAddress = "https://localhost:5001";
      using var channel = GrpcChannel.ForAddress(serverAddress);
      var client = new Greeter.GreeterClient(channel);
      var reply = client.SayHello(new HelloRequest { Name = "宋小宝!" });

      Console.WriteLine(reply.Message.ToString());

      Console.WriteLine("Press any key to exit...");
      Console.ReadKey();
}

使用服务器地址创建GrpcChannel,使用GrpcChannel对象实例化GreeterClient;

然后使用SayHello同步方法; 打印服务器响应结果。

3. 其他核心功能

3.1 通信方式

  • Unary RPC(一元Rpc调用): 上面的例子
  • Server streaming RPC :服务器流式RPC,客户端在其中向服务器发送请求,并读取消息流。客户端从返回的流中读取,直到没有更多消息为止。gRPC保证单个RPC调用中的消息顺序。
  • Client streaming RPC:客户端流式RPC,客户端使用流,写入一系列消息并发送到服务器。客户端写完消息后,它将等待服务器读取消息并返回响应。同样,gRPC保证了单个RPC调用中的消息顺序。
  • Bidirectional streaming RPC:双向流式通信,由于两个流是独立的,因此客户端和服务器可以按任何顺序读取和写入消息。例如,服务器可以等到收到客户端的所有消息后再写消息,或者服务器和客户端可以打“乒乓” (服务器收到请求,然后响应消息,然后客户端基于响应发送另一个消息,依此往返)

3.2 Metadata

元数据是以键值对列表的形式提供的有关特定RPC调用的信息(例如身份验证详细信息),其中键是字符串,值通常是字符串,但可以是二进制数据。元数据对于gRPC本身是不透明的:它允许客户端向服务器提供与调用相关的信息,反之亦然。

3.3 Channels

gRPC通道提供到指定主机和端口上的gRPC服务器的连接。 创建客户端存根时用到它,可以指定通道参数来修改gRPC的默认行为,例如打开或关闭消息压缩。 通道具有状态,包括已连接和空闲。

4. gRpc打乒乓球

针对脚手架项目,稍作修改--->乒乓球局

(考察gRpc双向流式通信、Timeout机制、异常处理):

客户端发送"gridsum", 服务端回发"musdirg"; 客户端再发送"gridsum", 往复......

① 添加接口

rpc PingPongHello(stream HelloRequest) returns (stream HelloReply);

② 实现服务契约

try
{
    while (!context.CancellationToken.IsCancellationRequested)
    {
         var asyncRequests = requestStream.ReadAllAsync();
         // 客户端与服务端"打乒乓"
         await foreach (var req in asyncRequests)
         {
               var send = Reverse(req.Name);
               await responseStream.WriteAsync(new HelloReply
               {
                   Message = send,
                   Id = req.Id +1
               });
               Debug.WriteLine($"第{req.Id}回合,服务端收到 {req.Name};开始第{req.Id + 1}回合,服务端回发 {send}");
          }
     }
}
catch(RpcException ex)
{
      System.Diagnostics.Debug.WriteLine($"{ex.Message}");
}

③ 客户端代码,控制乒乓球局在5s后终止

using (var cancellationTokenSource = new CancellationTokenSource( 5* 1000))
{
     try
     {
          var duplexMessage = client.PingPongHello(null, null, cancellationTokenSource.Token);
          await duplexMessage.RequestStream.WriteAsync(new HelloRequest { Id = 1, Name = "gridsum" }) ;

          var asyncResp = duplexMessage.ResponseStream.ReadAllAsync();
          await foreach (var resp in asyncResp)
          {
                var send = Reverse(resp.Message);
                await duplexMessage.RequestStream.WriteAsync(new HelloRequest {Id= resp.Id, Name = send });
                Console.WriteLine($"第{resp.Id}回合,客户端收到 {resp.Message}, 客户端发送{send}");
            }
       }
       catch (RpcException ex)
       {
           Console.WriteLine("打乒乓球时间到了(客户端5s后终断gRpc连接)");
       }
 }

https://github.com/zaozaoniao/GrpcAuthor

总结

gRPC是具有可插拔身份验证和负载平衡功能的高性能RPC框架。 使用protocol buffers定义结构化数据;使用不同语言自动产生的源代码在各种数据流中写入和读取结构化数据。

在本文中,您学习了如何使用protocol buffers 定义服务接口以及如何使用C#实现服务。最后,您使用gRPC双向流式通信创建了 "打乒乓球"Demo。

Additional Resources

https://developers.google.com/protocol-buffers/docs/csharptutorialhttps://www.grpc.io/docs/what-is-grpc/core-concepts/https://docs.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/why-grpc

本文分享自微信公众号 - Dotnet Plus(nodotnet),作者:小码甲

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-02-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • .NET WebSocket 核心原理初体验

    上个月我写了《.NET gRPC核心功能初体验》, 里面使用gRPC双向流做了一个打乒乓球的Demo, [实时][双向]这两个标签是不是很熟悉,对, WebSo...

    小码甲
  • gRPC在C#中的未来属于grpc-dotnet

    grpc-dotnet(Grpc.Net.Client[1]和Grpc.AspNetCore.Server[2] nuget 包)现在是.NET/C#中推荐的 ...

    CNCF
  • .NET Core ❤ gRPC

    这篇内容主要来自Microsoft .NET团队程序经理Sourabh Shirhatti的博客文章:https://grpc.io/blog/grpc-on-...

    张善友
  • C#8.0宝藏好物Async streams

    .NET诞生之初,就通过IEnumerable、IEnumerator提供迭代能力, 前者代表具备可枚举的性质,后者代表可被枚举的方式。 (看你骨骼惊奇,再送你...

    小码甲
  • 硬核技能k8s初体验

    Kubernetes 是一个软件系统,使你在数以万计的电脑节点上运行软件时就像 所有节点是以单个大节点一样, 它将底层基础设施抽象,这样做同时简化了应用开发、部...

    小码甲
  • 【译】.NET Core 3.0 Preview 3中关于ASP.NET Core的更新内容

    .NET Core 3.0 Preview 3已经推出,它包含了一系列关于ASP.NET Core的新的更新。

    Edison.Ma
  • What?VS2019创建新项目居然没有.NET Core3.0的模板?Bug?

    今天是个值得欢喜的日子,因为VS2019在今天正式发布了。作为微软粉,我已经用了一段时间的VS2019 RC版本了。但是,今天有很多小伙伴在我的《ASP.NET...

    依乐祝
  • .NET Core爱gRPC

    自2018年11月以来,微软的.NET团队一直与gRPC团队密切合作,为.NET Core开发新的完全托管的gRPC实现。

    CNCF
  • .NET Core 3.0 Preview 6中对ASP.NET Core和Blazor的更新

    我们都知道在6月12日的时候微软发布了.NET Core 3.0的第6个预览版。针对.NET Core 3.0的发布我们国内的微软MVP-汪宇杰还发布的官翻版的...

    Edi Wang

扫码关注云+社区

领取腾讯云代金券