dotnet core 之 gRPC

dotnet core gRPC


原文在本人公众号中,欢迎关注我,时不时的会分享一些心得

HTTP和RPC是现代微服务架构中很常用的数据传输方式,两者有很多相似之处,但是又有很大的不同。HTTP是一种规范性、通用性、非常标准的传输协议,几乎所有的语言都支持,如果要确保各平台无缝衔接,可以考虑使用HTTP协议,例如现在常规的RestFUL,整个传输过程通常使用Json数据格式。以至于不管是前端还是后端都可以很好的对接。
RPC协议不仅仅是服务间通信协议,甚至是进程间也存在。可以降低诸多微服务之间调用成本,屏蔽了通讯细节,调用远程方法处理数据时像调用本地方法一样丝滑顺畅。但是对前端和浏览器不是特别友好。
GRPC是google制定实现的一种Rpc形式,官网解释是:

gRPC是可以在任何环境中运行的现代开源高性能RPC框架。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证。它也适用于分布式计算的最后一英里,以将设备,移动应用程序和浏览器连接到后端服务。

gRPC主要包括四个特点

  1. 简单的服务定义且不局限于语言:gRPC基于ProtoBuf协议构建,该协议提供了强大的系列化工具和语言定义服务。
  2. 跨语言和平台:可自动为多语言或平台生成客户端和服务端内容。
  3. 快速启动和扩展性:只需极少代码就可以生成整个通讯环境,可以扩展数百万rpc请求。
  4. 双向流和集成身份验证:基于HTTP/2的传输机制以及双向流和而完全可集成的插入式身份验证机制。
    ProtoBuf协议
    该协议是一种序列化结构化数据的灵活,高效,自动化的机制,比xml更小,更快,更简单。您定义要一次构造数据的方式,然后可以使用生成的特殊源代码轻松地使用各种语言在各种数据流中写入和读取结构化数据。您甚至可以更新数据结构,而不会破坏已针对“旧”格式编译的已部署程序。
    协议文件定义方式:

    这是一个简单的定义,此文件在.proto文件中定义,与语言无关。每个消息类型都有一个或多个唯一编号的字段。每个字段都有一个名称和一个值类型,其中值类型可以是数字(整数或浮点数),布尔值,字符串等。定义好后可以使用编译器生成对应语言的操作对象。
    更多协议内容请参阅:https://developers.google.com/protocol-buffers/docs/overview

    .net Core3.0 中的Grpc

  5. 使用Visual Stduio 2019 创建一个gRPC服务

    请注意:此处创建的是使用ASP.NET Core的Grpc服务。也就是说,有WebHost去托管服务的。

    后面,我们使用Host通用主机进行托管。
  6. 先来看看Startup类

    图中这两行代码是关键,services.AddGrpc();将rpc注入到应用程序服务中,
    endpoints.MapGrpcService();则是在中间件启用监听rpc请求。
    默认情况下此时生成项目后,proto文件只会生成Serve的代码。客户端代码生成需要单独做配置。
    微软文档中是将proto文件拷贝到client中,去生成client代码。此时服务和客户端生成配置就不一样了:
<ItemGroup>
    <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
 </ItemGroup>

我本人习惯将生成的server和client放在一起,打包后供client端和server端使用,只需要这样设置:

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

配置好后重新生成项目,grpctool会自动生成服务端,客户端代码。

client调用方式(asp.net core gRPC):

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHello(
    new HelloRequest { Name = "World" });
Console.WriteLine(response.Message);

接下来,我们创建一个简单的示例

  1. 创建两个个Core控制台项目并添加文件夹Protos和Services,分别新增一个demo.proto文件和DemoService.cs文件
  2. 引入nuget包:
 <PackageReference Include="Google.Protobuf" Version="3.10.1" />
    <PackageReference Include="Grpc" Version="2.24.0" />
    <PackageReference Include="Grpc.Tools" Version="2.24.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" />
  1. 编辑csproj文件:使得支持同时生成client和server代码(作为demo,server端 应该只作为server。生成client和server的代码的应该单独抽出来)
  2. 服务端:重写GrpcExampleService.GrpcExampleServiceBase中的rpc方法(也就是.proto文件生成的代码内容中的rpc服务方法)
public class DemoService: GrpcExampleService.GrpcExampleServiceBase
    {
        public override Task<AskResponse> Ask(AskRequest request, ServerCallContext context)
        {
            return Task.FromResult(new AskResponse {Content = "Hello from Ask"});
        }

        public override Task<ResponseModel> GetName(RequestModel request, ServerCallContext context)
        {
            return Task.FromResult(new ResponseModel { Name = "Hello  Pluto" });
        }
    }
  1. 接下来就是创建启动项(HOST)了(GrpcServer):
    这次使用通用主机,不适用asp.net core webhost。
public class GrpcServer:IHostedService
    {
        private readonly GrpcExampleService.GrpcExampleServiceBase _sampleServiceBase;

        public GrpcServer(GrpcExampleService.GrpcExampleServiceBase sampleServiceBase)
        {
            _sampleServiceBase = sampleServiceBase;
        }

        /// <summary>
        /// 启动自己定义的rpc服务
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task StartAsync(CancellationToken cancellationToken)
        {
            return Task.Factory.StartNew(() =>
            {
                GrpcServiceManager.Start(GrpcExampleService.BindService(_sampleServiceBase));
            }, cancellationToken);
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task StopAsync(CancellationToken cancellationToken)
        {
            return Task.Factory.StartNew(() =>
            {
                GrpcServiceManager.Stop();
            }, cancellationToken);
        }
    }

GrpcServiceManager中就是真正的启动和停止grpc服务:


public class GrpcServiceManager
    {
        static Server server;
        public static void Start(ServerServiceDefinition bindService)
        {
            if (bindService == null)
                throw new ArgumentNullException("bindService");
            var services = new List<ServerServiceDefinition>() { bindService };
            Start(services); //todo 添加配置,拦截器等等
        }
        private static void Start(List<ServerServiceDefinition> services)
        {
            try
            {
                server = new Server()
                {
                    Ports = { new ServerPort("0.0.0.0", 8890, ServerCredentials.Insecure) }
                };

                foreach (var service in services)
                {
                    server.Services.Add(service);
                }
                server.Start();
                //todo consul 注册
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        public static void Stop()
        {
            try
            {
                server?.ShutdownAsync().Wait();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

        }
    }

注意:这里应该将proto协议 服务端客户端端进行分离,协议生成的代码打包后 被客户端项目和服务端项目引用,这里只是为了简便客户端直接会引用服务,因为要用到GrpcExampleService.GrpcExampleServiceClient

上边的todo 后再后续增加对应的功能。
这样服务端就创建完了。接下来就是创建客户端进行调用:

控制台客户端:
main中实现调用逻辑

static void Main(string[] args)
        {
            var  channel=new Grpc.Core.Channel("127.0.0.1",8890,ChannelCredentials.Insecure);
            var democlient=new GrpcExampleService.GrpcExampleServiceClient(channel);
            var res= democlient.Ask(new AskRequest
            {
                Cate = 0,
                Key = "1312"
            });
            var res2 = democlient.GetName(new RequestModel
            {
                Key = "1313"
            });
            Console.WriteLine($"Ask={res}.GetName={res2}");
        }

然后就可以了,启动服务端,然后再启动客户端,就可以看到调用结果了。

原文地址:https://www.cnblogs.com/pluto-net/p/11770419.html

时间: 2024-10-18 17:48:53

dotnet core 之 gRPC的相关文章

Dapr Pub/Sub 集成 RabbitMQ 、Golang、Java、DotNet Core

前置条件: <Dapr运用> <Dapr 运用之 Java gRPC 调用篇> <Dapr 运用之集成 Asp.Net Core Grpc 调用篇> 搭建 RabbitMQ Docker 搭建 RabbitMQ 服务 docker run -d --hostname my-rabbit --name some-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management 创建 rabbiqmq.yaml apiVers

centos 7 &amp;&amp; dotnet core 2.0 &amp;&amp; nginx &amp;&amp; supervisor

前提 系统:centos 7 目录:/home/wwwroot/www.wuball.com dotnet core 2.0 官方指引 sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc sudo sh -c 'echo -e "[packages-microsoft-com-prod]\nname=packages-microsoft-com-prod \nbaseurl=https://packages.mi

通过Swashbukle给DotNet Core Web API 增加自动文档功能

DotNet Core Web API给开发者提供了一个很好的框架来开发Restful的API.那么这些API接口该如何管理起来呢?Swagger是一个很好的选择,Swagger不需要开发者额外去维护接口文档,只要开发者的接口遵循Restful的规范,Swagger就会根据API接口生成文档. 对于前后端分离的开发模式,前后端开发者一般会先定义好接口,然后各自独立开发,后端开发者可以使用Swagger很快的生成没有业务逻辑的接口文档,接口返回的是Mock Data,这样前端开发人员就可以更早的开

dotnet core 使用 MongoDB 进行高性能Nosql数据库操作

好久没有写过Blog, 每天看着开源的Java社区流口水, 心里满不是滋味. 终于等到了今年六月份 dotnet core 的正式发布, 看着dotnet 社区也一步一步走向繁荣, 一片蒸蒸日上的大好景象. 不在绑定Windows, 相信众位dotneter的春天就要来了 废话不多说, 早就对dotnet core 跃跃欲试, 手头一个新项目也正计划使用dotnet core来开发. 正好自己做做调研, 就与大家分享一点使用MongoDB的经验. 首先, 安装VS Code, 并安装C#插件,

北京时间28号0点以后Scott Hanselman同志台宣布dotnet core 1.0 rtm

今日占住微信号头条的好消息<终于来了!微软.Net Core 1.0下载放出>.本人立马跑到官网http://dot.net看了一下,仍然是.net core 1.0 Preview 1版本. 看来该文所提供的下载链接应该是提前泄露的版本了吧. 有网友说,Red Hat DevNation的第二天也就是美太平洋时间27号上午(北京时间28号0点以后) Scott Hanselman同志才会登台宣布dotnet core 1.0 rtm. 查了一下dotnet cli tools 进度,如下:

dotnet Core 学习(一):环境搭建

1.环境搭建 Windows下环境搭建:http://www.microsoft.com/net/core#windowsvs2015 Linux下环境搭建:http://www.microsoft.com/net/core#linuxcentos Windows下VS Code环境配置: VS Code下载地址:https://code.visualstudio.com/ 安完成后,在VS Code中安装C#插件:C# for Visual Studio Code (powered by Om

【Step By Step】将Dotnet Core部署到Docker上

本教程的前提是,你已经在Linux服务器上已经成功的安装了Docker,我会大概介绍在此过程中用到的Docker命令,并不会介绍所有的Docker命令(因为我也不会). 一.在Docker中运行Dotnet Core Hello World 微软官方提供了已经集成好Dotnet Core运行所需环境的Docker Image,我们可以直接使用命令: docker run -it microsoft/dotnet:latest 其中 -i :表示以后台模式开始Docker Container -t

dotnet core 实践——日志组件Serilog

 前几天把基于quartz.net的部分项目代码移植到了dotnet core ,但是没增加日志功能,原因是没找到合适的组件. 今天终于找到了Serilog: https://github.com/serilog/serilog 源码 就大概讲一下: 1, vs 2015  新建Console Application (.NET Core) 项目. 2, 程序包管理器控制台: 安装如下组件:Serilog,Serilog.Sinks.Literate,Serilog.Sinks.RollingF

dotnet core 出现Can not find runtime target for framework &#39;.NETCoreApp,Version=v1.6&#39; 的解决办法

如果你在更新dotnet core新的类库后运行程序提示如下的错误: Can not find runtime target for framework '.NETCoreAPP, Version=v1.0' compatible with one of the target runtimes: 'win10-x64, win81-x64, win8-x64, win7-x64'. Possible causes:        The project has not been restored