zoukankan      html  css  js  c++  java
  • ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)

    早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把。同时记录体验的过程。如果你也想按照本文的步骤体验的话,那你得先安装.NET Core3.0预览版的SDK。至于开发工具我用的时VS2019,当然你也可以使用VS Code进行。

    作者:依乐祝
    原文地址:https://www.cnblogs.com/yilezhu/p/10631420.html

    gRPC的简单介绍

    gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架。 有关 gRPC 基础知识的详细信息,请参阅 gRPC 文档页

    gRPC 的主要优点是:

    • 现代高性能轻量级 RPC 框架。
    • 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现。
    • 可用于多种语言的工具,以生成强类型服务器和客户端。
    • 支持客户端、服务器和双向流式处理调用。
    • 使用 Protobuf 二进制序列化减少对网络的使用。

    这些优点使 gRPC 适用于:

    • 效率至关重要的轻量级微服务。
    • 需要多种语言用于开发的 Polyglot 系统。
    • 需要处理流式处理请求或响应的点对点实时服务。

    ASP.NET Core 3.0上gRPC服务模板初体验

    创建gRPC服务

    1. 打开VS2019 从 Visual Studio“文件”菜单中选择“新建” > “项目”。(由于我是新打开的VS,所以按照如下图所示创建新项目)

      1554009071721

    2. 如下图所示,选择创建《ASP.NET Core Web 应用程序》,然后点击下一步

      1554009107868

    3. 在此页面按照下图所示,输入项目名称,位置,解决方案名称,然后点击右下角的“创建”按钮进行创建。

      1554009210208

    4. 你以为上述步骤中点击“创建”就结束了嘛?说好的要创建gRPC服务模板的,所以,点击上面的创建后会弹出如下图所示,让你选择服务模板的窗口,这里按照下图所示选择gRPC服务模板,然后再次点击右下角的创建,才是真正的创建项目。

      1554009368040

    5. 创建成功后,会出现如下图所示的项目结构

      1554009441048

    6. 至此,我们就创建好了一个gRPC服务的模板,接下来我们先测试一番,然后再好好的看下这个模板的结构吧

    测试gRPC服务

    1. 首先打开HelloGrpc.Server 这个服务端的工作目录,然后Shift+鼠标右键弹出如下图所示的右键菜单,如图所示打开ps窗口

      1554009655486

    2. 输入dotnet run 命令运行此gRPC服务端项目,如下图所示,说明服务端启动正常,并开始监听对应的端口。

      1554009713142

    3. 同样的方法,我们启动客户端,这时候客户端会向该服务端发送一条包含具有其名称“GreeterClient”的消息的问候信息。 该服务端将发送一条消息“Hello GreeterClient”作为响应,并显示在命令提示符中。如下图所示:

      1554009820515

    4. 至此,gRPC服务模板创建的服务端以及客户端测试成功。下面我们就好好的探究一下这个服务模板吧。

    gRPC模板解析

    HelloGrpc.Server 服务的端项目中有如下几个文件

    • greet.proto:greet.proto 文件定义 Greeter gRPC,且用于生成 gRPC 服务器资产。
    • Services 文件夹:包含 Greeter 服务的实现。
    • appSettings.json:包含配置数据,如 Kestrel 使用的协议。(熟悉ASP.NET Core的你一定很熟悉)
    • Program.cs:包含 gRPC 服务的入口点。(熟悉ASP.NET Core的你一定很熟悉)
    • Startup.cs:IWebHostBuilder的启动配置文件,包含配置应用行为的代码。(熟悉ASP.NET Core的你一定很熟悉)

    gRPC 客户端 HelloGrpc.Client 文件:

    Program.cs 包含 gRPC 客户端的入口点和逻辑。

    下面我们再打开每个文件看看里面究竟是什么东东吧。

    proto文件

    proto

    GRPC使用约定优先的API开发方法。默认情况下,使用协议缓冲区(Protobuf)作为接口设计语言(IDL)。这个.proto文件包含:

    • GRPC服务的定义。
    • 在客户端和服务器之间发送的消息。

    有关Protobuf文件语法的更多信息,请参见正式文件(原型).

    如我们模板中创建的greet.proto 文件内容如下:

    syntax = "proto3";
    
    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;
    }
    
    • 定义Greeter服务。
    • 这个Greeter服务定义SayHello请求。
    • SayHello发送HelloRequest消息并接收HelloResponse信息:
      那么你可能要问了,这个.proto文件是如何包含在项目中的呢,其实,如果你打开.csproject文件就会看到,通过将该文件添加到<Protobuf>的ItemGroup中即可,如下所示:
    <ItemGroup>
      <Protobuf Include="..Protos*.proto" GrpcServices="Server" />
      <Content Include="@(Protobuf)" LinkBase="" />
    </ItemGroup>
    

    C#对.proto文件的工具支持

    工具包Grpc.Tools 被用来从.proto文件生成C#文件。生成的资产(文件)具有如下特性:

    • 每次构建项目时都会根据需要进行生成。
    • 生成的文件不会被添加到项目或签入源代码管理。
    • 生成的C#文件是包含在OBJ目录。

    服务器和客户端项目都需要此包。Grpc.Tools可以通过在VisualStudio中使用包管理器或添加<PackageReference>到项目文件:

    XML复制

    <PackageReference Include="Grpc.Tools" Version="1.19.0-pre1" PrivateAssets="All" />
    

    工具包在运行时并不是必需的,因此,应该用PrivateAssets="All".

    Services 文件夹中的具体的gRPC服务

    我们知道Grpc.Tools工具包将根据.proto文件的定义翻译并生成对应的C#类型的文件。

    对于服务器端资产,将生成一个抽象的服务基类型。基类型包含在.proto文件中包含的所有GRPC调用的定义。然后,您将创建从此基类型派生的具体服务实现,并实现GRPC调用的逻辑。对于前面描述的greet.proto示例,将生成包含虚拟SayHello方法的抽象GreeterBase类型。具体的实现GreeterService重写该方法并实现处理GRPC调用的逻辑。
    正如HelloGrpc.Server项目中的ServicesGreeterService.cs中的代码

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

    对于客户端,将生成一个具体的客户端类型中的GRPC调用。.proto文件被转换为可以调用的具体类型上的方法。为greet.proto前面描述的示例,一个具体的GreeterClient类型生成。这个GreeterClient类型包含SayHello方法,可以调用该方法来启动对服务器的GRPC调用。

    public class Program
    {
        static async Task Main(string[] args)
        {
            // Include port of the gRPC server as an application argument
            var port = args.Length > 0 ? args[0] : "50051";
    
            var channel = new Channel("localhost:" + port, ChannelCredentials.Insecure);
            var client = new Greeter.GreeterClient(channel);
    
            var reply = await client.SayHelloAsync(
                                          new HelloRequest { Name = "GreeterClient" });
            Console.WriteLine("Greeting: " + reply.Message);
    
            await channel.ShutdownAsync();
    
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
    

    默认情况下,分别生成服务器和客户端资产。.proto文件包含在<Protobuf>项目组。若要确保仅在服务器项目中生成服务器资产,GrpcServices属性设置为Server.

    XML复制

    <ItemGroup>
      <Protobuf Include="..Protos*.proto" GrpcServices="Server" />
      <Content Include="@(Protobuf)" LinkBase="" />
    </ItemGroup>
    

    类似地,属性设置为Client在仅在客户项目中生成。

    Startup

    Startup中我们发现跟普通的ASP.NET Core程序有所不同,具体的如下图所示:在ConfigureServices 服务中引入了gRPC服务,然后在Configure加入了路由

    1554014291599

    而这里需要引入三个与gRPC相关的nuget包

    这里需要说明的是

    ASP.NET Core 中间件和功能共享路由管道,因此可以将应用程序配置为服务其他请求处理程序。其他请求处理程序(如MVC控制器)可以与配置的GRPC服务路由并行工作。

    其他需要说明的内容

    与ASP.NET Core 接口的集成

    GRPC服务可以完全访问ASP.NETCore功能,如依赖注入(Di)和日志功能。例如,服务实现可以通过构造函数解析DI容器中的记录器服务:

    public class GreeterService : Greeter.GreeterBase
    {
        public GreeterService(ILogger<GreeterService> logger)
        {
        }
    }
    

    默认情况下,GRPC服务可以解析具有任意生存期的其他DI服务(Singleton, Scoped, or Transient)。

    在GRPC方法中解析HttpContext

    GRPC 应用程序接口提供对某些HTTP/2消息数据的访问,例如method, host, header, and trailers。访问是通过ServerCallContext参数传递给每个GRPC方法:

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

    ServerCallContext不提供对所有ASP.NET 接口中HttpContext的完全访问。GetHttpContext扩展方法提供对表示ASP.NET API中底层HTTP/2消息的httpContext的完全访问:

    public class GreeterService : Greeter.GreeterBase
    {
        public override Task<HelloReply> SayHello(HelloRequest request, 
            ServerCallContext context)
        {
            var httpContext = context.GetHttpContext();
    
            return Task.FromResult(new HelloReply
            {
                Message = "Using https: " + httpContext.Request.IsHttps
            });
        }
    }
    

    请求体数据速率限制

    默认情况下,Kestrel服务器设置为最小请求主体数据速率。对于客户端流式和双工流式的请求,此速率可能不满足,并且连接可能超时。当GRPC服务包括客户端流和双工流调用时,必须禁用最小请求正文数据速率限制:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
    
        public static IHostBuilder CreateHostBuilder(string[] args) =>
             Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
            webBuilder.ConfigureKestrel((context, options) =>
            {
                options.Limits.MinRequestBodyDataRate = null;
            });
        });
    }
    
    
    

    参考文章

    总结

    今天分享的内容有点多,目的就是使记录尽可能的详细,尽可能用通俗易懂的语言来进行描述,让大家能用起来。在asp.net core3.0中把grpc服务作为第一等公民进行支持,所以我们有必要进行下了解。可能很多朋友会有疑问了,我Web API用的爽歪歪,干嘛还要用gRPC这种远程过程调用协议啊。关于这个问题,我准备再单独开一篇文章进行讲解,最后感谢大家的阅读,码字不易,多多推荐支持吧!

  • 相关阅读:
    python RabbitMQ gRPC 实践经验
    python 数据库实践经验
    python GUI相关
    angularjs中的$watch、$digest、$apply
    css选择器优先级
    angularjs基本理解
    如何编写符合web标准的XHTML文档
    跨域问题
    如何养成良好的书写代码习惯
    ie常见兼容问题
  • 原文地址:https://www.cnblogs.com/yilezhu/p/10631420.html
Copyright © 2011-2022 走看看