ASP.NET Core 使用 gRPC 初探

(RPC通讯示意图)

为什么突然说到gRPC呢,其实以前就想说一说这个东西,也想尝试使用一下,一直没有机会,一直看我公众号的小伙伴肯定都知道,这几天一直在录制一个《eShopOnContainer微服务架构》系列,现在已经是8期了,里边涵盖了使用ASP.NETCore开发微服务的常用的基本的知识技能,具体的你可以看我的视频就行,B站也同步更新。

既然要说到了微服务,那肯定就离不开服务间调用,自然而然的就联系到了常用的一个框架——gRPC了,那今天就简单的说一说这个框架,也算是一个刚入门的,比较简单,后边我也会持续跟进讲解。

 划 

 重 

 点 

gRPC是什么?

用官网的一句话就是:A high-performance, open-source universal RPC framework。

要说gRPC,那就先说下什么的RPC框架,所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样。

gRPC就是一个由Google开源的,跨语言的,高性能的远程过程调用(RPC)框架。gRPC使客户端和服务端应用程序可以透明地进行通信,并简化了连接系统的构建。它使用HTTP/2作为通信协议,使用 Protocol Buffers 作为序列化协议。

可能第一次看到这种通信框架比较陌生,介绍的也比较官方和抽象,这里说一下另一个常用的服务间通讯的方案,你可能就明白了,那就是RESTFul风格的API,想必每个人都用过RestfulAPI吧,这里就先简单说下RestfulAPI,如果这个还不是很理解的话,建议死记硬背。

1、REST,即Representational State Transfer的缩写。直接翻译的意思是"表现层状态转化"。
2、它是一种互联网应用程序的API设计理念:URL定位资源,用HTTP动词(GET,POST,DELETE,PUT,DETC)描述操作,比如只需要知道/api/blog,你就知道了他的常见的CURD多种操作。

3、简单来说就是url地址中只包含名词表示资源,使用http动词表示动作进行操作资源,软件和网络这两个领域一定程度上结合起来

4、之所以灵活,是因为他很少参与业务逻辑,只定义资源操作


看完了RestfulAPI,你应该就能明白gRPC是干什么的了吧。

那两者有什么区别呢,平时在前后端分离或者移动端需要后端api的场景下,经常使用Restful丰富的API,既然大家已经习惯并熟悉了Restful,为何还用gRPC呢?

PS:下边的内容我基本是摘抄于官网和网络,文末有参考连接,今天主要是介绍下如何操作代码,文字讲解不是重点。

为什么要使用gRPC?

问题:既然是server/client模型,那么我们直接用restful api不是也可以满足吗,为什么还需要RPC呢?

我这里简单说明下优缺点和比较,说说到底使用gRPC有什么好处。

gRPC 和 Restful API

gRPC和Restful API都提供了一套通信机制,用于server/client模型通信,而且它们都使用http作为底层的传输协议(严格地说, gRPC使用的http2.0,而Restful api则不一定)。

不过gRPC还是有些特有的优势,如下:

1、gRPC可以通过protobuf来定义接口,从而可以有更加严格的接口约束条件。

2、通过protobuf可以将数据序列化为二进制编码,这会大幅减少需要传输的数据量,从而大幅提高性能。

3、gRPC可以方便地支持流式通信.

场景与好处????

1、需要对接口进行严格约束的情况。

比如我们提供了一个公共的服务,很多人,甚至公司外部的人也可以访问这个服务,这时对于接口我们希望有更加严格的约束,我们不希望客户端给我们传递任意的数据,尤其是考虑到安全性的因素,我们通常需要对接口进行更加严格的约束。这时gRPC就可以通过protobuf来提供严格的接口约束。

2、对于性能有更高要求的轻量级微服务。

有时我们的服务需要传递大量的数据,而又不希望影响到我们的性能,这个时候也可以考虑gRPC服务,因为通过protobuf我们可以将数据压缩编码转化为二进制格式,通常传递的数据量要小得多,而且通过http2我们可以实现异步的请求,从而大大提高了通信效率。

同时,更适应于网络受限的环境,使用 Protocol Buffers二进制序列化消息,该序列化始终小于等效的JSON消息,对网络带宽需求比JSON小。

 

3、需要对接多种语言的微服务的情况。

比如我们公司的项目,有JAVA组,有Python组,或者.NETCore组别,每个组当然负责各自独立的子服务部分,那就需用用到不同语言之间的服务调用问题,不希望出现兼容性问题。这个时候就用到了gRPC了,它协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现。可用于多种语言的工具,以生成强类型服务器和客户端。gRPC工具支持所有流行的开发语言,使gRPC成为多语言开发环境的理想选择。

4、需要处理流式处理请求或响应的点对点实时服务

gRPC用更小的网络带宽,又支持客户端、服务器和双向流式处理调用,更好的帮助处理流式请求。

(理论上通过http2.0就可以使用streaming模式, 但是通常web服务的Restful api似乎很少这么用,通常的流式数据应用如视频流,一般都会使用专门的协议如HLS,RTMP等,这些就不是我们通常web服务了,而是有专门的服务器应用。)

也并不是十全十美的????

任何开发工具或者项目框架都不是十全十美的,就算是K8s、微服务或者DDD这么火热的技术也并不是无脑就上的,gRPC框架也有一定的弊端,或者至少是某些场景下是不适合的:

1、浏览器可访问的API。

 浏览器不完全支持gRPC。虽然gRPC-Web可以提供浏览器支持,但是它有局限性,引入了服务器代理

2、广播实时通信

gRPC支持通过流进行实时通信,但不存在向已注册连接广播消息的概念

3、进程间通信

进程必须承载HTTP/2才能接受传入的gRPC调用,对于Windows,进程间通信管道是一种更快速的方法。

如何.NETCore上使用gRPC?

关于如何在ASP.NETCore上使用gRPC,这里有两种方法,第一是直接创建gRPC模板项目,第二个就是在在ASP.NETCore项目上创建gRPC服务。其实这两个原理和操作流程都是差不多的,我这里都说一下吧。

通过模板创建gRPC服务

打开VS2019(版本至少16.3+),新建项目,搜索"gRPC",就能看到一个选项,

点击下一步,填写好项目名称和项目地址以后,点击创建,

然后可以看到NetCore版本是3.1,然后不勾选Docker,点击创建。

等待新建好项目,就可以看到默认的文件是这样的,其实和我们创建ASP.NETCore项目是很相似的,如果说真的不一样,就是依赖包和多了一个Protos的文件夹,那下边我们来一一看看都是怎么作用的:

1、依赖包

Grpc.AspNetCore是gRPC结合ASP.NETCore封装的一个类库,其中很重要的是下边的两个依赖包,第一个就是Protobuf,第二个就是Tools,从名字上应该都能大概猜出来是干啥的,肯定有一个是解析protobuf文件的,一个是工具包,负责一些操作的。

2、Protos文件夹

在文章的开头我们已经说过了,gRPC很重要的一点,就是在请求和相应的的时候需要用到一个.proto的文件,用来定义服务和提供参数已经响应的参数。

默认的内容是这样的:

  // 语法结构,使用pb3syntax = "proto3";// 定义命名空间,一般是项目名或者解决方案名option csharp_namespace = "GrpcService1";// 定义服务的包package greet;// 定义具体的服务service Greeter {// 定义某一个方法API,格式是:rpc 方法名(请求参数对象名) returns(返回参数对象名)rpc SayHello (HelloRequest) returns (HelloReply);}// 定义请求的对象名message HelloRequest {// 有一个属性字段是namestring name = 1;}// 定义返回的对象名message HelloReply {// 有一个返回的字段是messagestring message = 1;}

可以看到虽然是扩展名是.proto的文件,但是语法结构很像一个.cs文件,语法上也类似,当然只不过是类似,具体的意思我已经在上边注释了,你看看就能明白。

你可能会好奇,那我定义好了这一个文件,怎么来使用呢,别着急,分成两步,咱们先说第二步定义具体服务,第一步先卖个关子。

3、GreeterService服务

上边我们定义好了proto文件,下边就需要针对这个配置,设计服务了,因为proto仅仅是定义了服务,还没有具体的内容,那很简单,就直接看代码吧。

 /// <summary>/// 根据.proto定义具体的服务/// GreeterService可以任意定义/// Greeter.GreeterBase 根据.proto文件中定义的规则来/// </summary>public class GreeterService : Greeter.GreeterBase{// 和ASP.NETCore一样,可以使用依赖注入和服务private readonly ILogger<GreeterService> _logger;public GreeterService(ILogger<GreeterService> logger){_logger = logger;}/// <summary>/// 重写 设计对应的多个接口/// 一般都是异步处理/// </summary>/// <param name="request"></param>/// <param name="context"></param>/// <returns></returns>public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context){return Task.FromResult(new HelloReply{Message = "Hello " + request.Name});}}

我也同样的把注释都写上了,其实内容都是很简单的,我们都已经用了ASPNETCore这么久了,肯定都一样都能看明白,有两个问题肯定你会问:

第一、定义服务我明白,但是继承的父类Greeter.GreeterBase是如何处理的呢?

这个就是我第二步说完.proto文件的时候卖的那个关子,我们定义好了.proto文件后,系统会自动给我们创建生成服务、客户端和消息(表示传递的数据)的C# Class,但是需要一个操作:

右键项目,编辑项目文件,可以看到有一个配置:

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

这个是官方默认模板已经创建好的,是一个Server类型的服务,Include对应的文件,然后项目就能自动给我们创建好了父类,你可以从obj文件夹看到:

这个时候,就可以继承了。

第二、如何重写对应的方法呢?

很简单,直接针对当前的类型,alt+enter,在智能提示里,找到重写,就可以看到要重写的接口了:

4、appsettings.json

注意这里别之前不一样的地方,就是定义了一个节点:

"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http2"}}

在上边我们说过,gRPC 需要 HTTP/2。 适用于 ASP.NET Core 的 gRPC 验证 HttpRequest.Protocol 为 HTTP/2。

Kestrel 在大多数新式操作系统上支持 HTTP/2。默认情况下,Kestrel 终结点配置为支持 HTTP/1.1 和 HTTP/2 连接。

5、Startup.cs

其他的文件内容都类似,我就不多说了,我们都知道,要用一个服务,就需要注册这个服务,那就肯定需要是Startup里,

 // 注册grpc服务services.AddGrpc();// 在结点路由里配置指定的服务app.UseEndpoints(endpoints =>{endpoints.MapGrpcService<GreeterService>();endpoints.MapGet("/", async context =>{await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");});});

项目启动,

可以看到,只有https安全协议的,因为上边已经说过了使用gRPC必须是http/2的,同样也是需要https安全协议的。

到这里就没有问题了,说完了系统默认模板创建的方案,那现在我们不用这个方案,尝试一下,如果已经创建好了一个NetCore的API项目,比如我的Blog.Core,如何在这个基础上,创建gRPC服务呢?

基于ASP.NETCore项目创建

因为上边我们已经讲完了对应的内容和注意事项,为了篇幅不罗嗦,我就直接创建,看看是否真的可以:

还是在当然解决方案,创建一个netcore的api项目,然后添加三个nuget包:

<PackageReference Include="Google.Protobuf" Version="3.11.2" />
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.25.0" />
<PackageReference Include="Grpc.Tools" Version="2.25.0" PrivateAssets="All" />  

接着添加helloworld.proto文件,配置.csproj项目配置,包含当前的.proto文件,创建HelloWorldservice.cs服务类,继承刚刚创建好的父类Hello.HelloBase,最后,注册服务,配置中间件,相应的操作可以看下边的视频:

现在我们已经定义了好了server端的服务,那如何发起调用呢,需要一个client客户端。

如何发起调用?

1、创建一个netcore的控制台

还是在该解决方案中,添加一个控制台项目

然后添加三个依赖包:

<ItemGroup><PackageReference Include="Google.Protobuf" Version="3.13.0" /><PackageReference Include="Grpc.Net.Client" Version="2.32.0" /><PackageReference Include="Grpc.Tools" Version="2.33.1"><PrivateAssets>all</PrivateAssets><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets></PackageReference>
</ItemGroup>

注意,这里我们并没有添加其他的项目引用!

2、把Hello.proto拷贝到控制台

这个很简单,只需要直接把文件夹和文件直接拖动过去就行了。

然后配置下.csproj文件,修改下gprc的服务类型,一定是client:

<ItemGroup><Protobuf Include="Proto\helloworld.proto" GrpcServices="Client" />
</ItemGroup>

3、发起调用

我这里就直接写代码了

 class Program{static async System.Threading.Tasks.Task Main(string[] args){// 创建通道var channel = GrpcChannel.ForAddress("https://localhost:5001");// 发起客户端调用var client = new Hello.HelloClient(channel);// api请求,传递参数var response = await client.SayHelloAsync(new HelloRequest { Name = "World" });Console.WriteLine("Greeting: " + response.Message);}}

大概意思就是这样的,应该能够看懂的。

运行我们的gRPC服务,也就是运行core的webapi程序,然后运行客户端控制台:

看到没有,我们并没有在控制台去引用我们的gRPC服务端的代码,只需要一个.proto文件,就能够像调用方法一样,去调用其他服务端项目的服务,这就是很大的直观上的好处。

当然好处还有很多的,比如什么是流式,如何实现服务间调用,如何网关配置等等等等,咱们下次再见吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

源码都没调试过,怎么能说熟悉 redis 呢?

一&#xff1a;背景 1. 讲故事记得在很久之前给初学的朋友们录制 redis 视频课程&#xff0c;当时结合了不少源码进行解读&#xff0c;自以为讲的还算可以&#xff0c;但还是有一个非常核心的点没被分享到&#xff0c;那就是源码级调试&#xff0c; 对&#xff0c;读源码还远远…

算法 - DFS/BFS

写DFS函数的时候首先确定当前位置是否已经加入路径 DFS函数大概率会传递“位置信息”&#xff0c;根据位置信息获取下一步的选择&#xff0c;&#xff08;大部分是在循环中&#xff09;选择、执行、回退 在哪做选择&#xff0c;就在哪退出选择&#xff0c;参考题9 def DFS()…

你想象中的Task后续,很简单?

【导读】前不久&#xff0c;写过一篇关于Task的简短文章&#xff0c;通过评论和转载得到好评&#xff0c;刚好我昨晚又写了一篇实现简单的消息队列也提到了Task&#xff0c;难道不应该是看具体执行什么操作&#xff0c;再考虑最佳方案&#xff1f;本文我们再次通过简短内容谈谈…

5G在工业互联网应用的机遇与挑战

移动通讯经过十年一代的发展&#xff0c;已经从1G发展到了5G&#xff0c;峰值速率实现十年千倍的增长&#xff0c;1G到4G是面向个人的&#xff0c;而5G是面向产业互联网和智慧城市服务。5G是一个颠覆性的技术&#xff0c;低时延&#xff08;每秒钟下载一部高清电影&#xff09;…

[C#.NET 拾遗补漏]10:理解 volatile 关键字

要理解 C# 中的 volatile 关键字&#xff0c;就要先知道编译器背后的一个基本优化原理。比如对于下面这段代码&#xff1a;public class Example {public int x;public void DoWork(){x 5;var y x 10;Debug.WriteLine("x " x ", y " y);} }在 Releas…

跟我一起学.NetCore之MediatR好像有点火

前言随着微服务的流行&#xff0c;而DDD(领域驱动设计)也光速般兴起&#xff0c;CRQS(Command Query Responsibility Seperation--命令查询职责分离)、领域事件名词是不是经常在耳边环绕&#xff0c;而MediatR组件经常用来对其技术的落地&#xff0c;凭这&#xff0c;小伙伴们说…

不想写脚本清理 mongodb 中的垃圾数据,ttlIndex 能帮到你!

mongodb一直都在不断的更新&#xff0c;不断的发展&#xff0c;那些非常好玩也非常实用的功能都逐步加入到了mongodb中&#xff0c;这不就有了本篇对ttlindex的介绍&#xff0c;刚好我们的生产业务场景中就有一个案例。。。一&#xff1a;案例分析 生产的推荐系统要给用户发送短…

后端学习 - 基础 《Java编程的逻辑》读书笔记

文章目录一 基础概念1 有关Java2 JVM / JDK / JRE3 与C的联系和区别4 各类型数据占用空间大小5 和 equals() 的区别、hashCode() 方法6 包装类型7 final 关键字8 参数传递机制&#xff1a;值传递9 String 的内存情况10 访问修饰符11 引用拷贝、浅拷贝与深拷贝三 面向对象1 面向…

cheatengine找不到数值_彩票中奖500万,领了还不到一半?这些问题不解决,钱都拿不走...

长期以来&#xff0c;“一夜暴富”是很多人梦寐以求的梦想&#xff0c;而作为最能让人“一夜暴富”的方式要数我国的福利彩票了&#xff0c;这也是很多人最容易活动暴富的机会&#xff0c;不少彩民长久以来一直买彩票的梦想就是“一夜暴富”。而突然暴富是很多人的梦想&#xf…

一站式Web开发套件BeetleX.WebFamily

BeetleX.WebFamily是一款前后端分离的Web开发套件&#xff0c;但它并不依赖于nodejs/npm/webpack等相关工具&#xff1b;而使用自身实现的方式来完成前后端分离的Web应用开发&#xff1b;套件以组件的方式发布&#xff0c;只需要在项目引用相关组件即可实现前后端分离开发&…

.NET架构小技巧(2)——访问修饰符正确姿势

在C#中&#xff0c;访问修饰符是使用频率很高的一组关键字&#xff0c;一共四个单词六个组合&#xff1a;public,internal,protected internal,protected,private protected,private&#xff0c;如果你对这些关键字非常清楚&#xff0c;请跳过&#xff0c;节省时间&#xff1b;…

能源36号文解读_IDC报告预测:今年中国新能源汽车销量将达116万辆,未来五年复合增长率36%_详细解读_最新资讯_热点事件...

编者按&#xff1a;本文来自36氪「 未来汽车日报」&#xff0c;(微信公众号ID&#xff1a;auto-time)&#xff0c;作者&#xff1a;秦章勇。 来源&#xff1a;IDC作者 | 秦章勇编辑 | 周游12月3日&#xff0c;在2020世界智能汽车大会上&#xff0c;IDG亚洲(国际数据(亚洲)集团)…

后端学习 - 容器

文章目录一 简介二 底层数据结构总结1 List2 Set3 Queue4 Map三 Collection 的子接口 List1 ArrayList 与 Vector2 ArrayList 与 LinkedList3 ArrayList 的 JDK 7/8 差异4 ArrayList 的构造方法与扩容机制*四 Collection 的子接口 Set1 HashSet、LinkedHashSet 和 TreeSet2 Has…

简单聊聊AspNetCore的启动流程

首先&#xff0c;得和大家达成一个共识&#xff0c;即AspNetCore项目其实就是一个控制台项目。可以简单的理解&#xff0c;AspNetCore就是将一个Web服务器宿主在一个进程(即控制台)中&#xff0c;然后它在这个进程中进行http请求的监听处理。AspNetCore中默认使用kestrel作为we…

共聚焦图片怎么加标尺_聚焦扶贫政策,打造小康生活

导语&#xff1a;农村独栋小楼、整洁的水泥路……扶贫产业蓬勃发展&#xff0c;我省结合实际&#xff0c;狠抓特色产业&#xff0c;助力脱贫攻坚&#xff0c;实现乡村振兴。武宁县&#xff1a;“四个聚焦”巩固脱贫成果2020年是全面建成小康社会目标实现之年&#xff0c;是全面…

后端学习 - 并发编程

文章目录零 基本概念1 CAS、ABA 问题和原子变量2 this 引用逸出3 不变性 immutable4 同步、异步、阻塞、非阻塞5 JMM6 同步方案演示&#xff1a;计数器 demo*一 进程与线程1 区别与联系2 Java内存区域3 线程组4 线程的上下文切换5 并发与并行6 线程的生命周期与状态二 线程间的…

打造跨平台.NET Core后台服务

续之前讲的在TopShelf上部署ASP.NET Core程序&#xff0c;作为后台服务运行&#xff0c;自从.NET Core 3.0出现以后&#xff0c;出现了自带的Generic Host&#xff0c;使得自托管服务变为可能。这种方式和TopShelf方式一样&#xff0c;可以直接F5进行服务的调试&#xff0c;也为…

iphone桌面横屏设置在哪里_我和我各司其职的桌面们

作者&#xff1a;旭彦兮沐桌面是只属于我们自己一个人的舞台&#xff0c;是与我们独处的好伙伴。好好布置一下自己的桌面&#xff0c;能在很大程度上保持我们心情的愉悦和做事情的效率&#xff0c;让我们保持专注当下的沉浸感。我最早了解到「桌面文化」其实是很早之前了&#…

后端学习 - RabbitMQ

文章目录一 MQ 的作用与基本概念1 流量削峰2 应用解耦3 异步调用4 四个基本概念二 核心模式1 工作队列模式&#xff08;Work Queue&#xff09;2 发布/订阅模式&#xff08;Publish / Subscribe&#xff09;3 路由模式&#xff08;Routing&#xff09;4 主题模式&#xff08;To…

dubbo k8s 服务发现_工商银行基于 Dubbo 构建金融微服务架构的实践-服务发现篇

简介&#xff1a; Dubbo 作为分布式微服务框架&#xff0c;众多公司在实践中基于 Dubbo 进行分布式系统架构。重启开源后&#xff0c;我们不仅看到 Dubbo 3.0 最新的 Roadmap 发布&#xff0c;而且还看到阿里在自身电商开始推进 Dubbo 和内部 HSF 的融合&#xff0c;并在 双11 …