【gRPC】 在.Net core中使用gRPC
最近在學(xué)習(xí).net core的微服務(wù)體系架構(gòu)。微服務(wù)之間的通信常常通過gRPC進(jìn)行同步通信,但是需要注意的是,大多數(shù)微服務(wù)之間的通信是通過事件總線進(jìn)行異步通信。在微軟介紹.net微服務(wù)體系架構(gòu)的項(xiàng)目eShop中,微服務(wù)之間進(jìn)行同步通信的場(chǎng)景很多,大多數(shù)都是HTTP/REST,目前只有自定義聚合器與微服務(wù)之間通信是使用的gRPC。整套微服務(wù)架構(gòu)體系,其實(shí)除了客戶端與網(wǎng)關(guān)(BFF)之間,使用HTTP/REST,均可使用gRPC(只要網(wǎng)關(guān)支持HTTP/REST與gRPC的轉(zhuǎn)換)
BFF轉(zhuǎn)發(fā)外部請(qǐng)求
微服務(wù)之間
自定義聚合器與微服務(wù)
1.gRPC是什么?
A high-performance, open-source universal RPC framework。
gRPC是一個(gè)高性能的通信協(xié)議,它基于HTTP/2和protocol buffers。它是微服務(wù)之間進(jìn)行同步通信的主要選擇。與之相對(duì)的,就是其他協(xié)議,如AMQP的異步通信隊(duì)列或者發(fā)布/訂閱模式。
RPC(remote procedure call 遠(yuǎn)程過程調(diào)用)框架實(shí)際是提供了一套機(jī)制,使得應(yīng)用程序之間可以進(jìn)行通信,而且也遵從server/client模型。使用的時(shí)候客戶端調(diào)用server端提供的接口就像是調(diào)用本地的函數(shù)一樣.
與HTTP/JSON相比,gRPC的優(yōu)勢(shì):
高性能:協(xié)議緩沖區(qū)是一種二進(jìn)制的高性能序列化機(jī)制。根據(jù)語言的不同,實(shí)現(xiàn)協(xié)議緩沖區(qū)的速度比JSON序列化快8倍,而消息的大小可能比JSON序列化小60%-80%。
支持?jǐn)?shù)據(jù)流,說白了,還是快
約定顯示,與語言無關(guān):使用proto文件定義服務(wù)端與客戶端之間的約定
2.在.net core中使用gRPC
在.NET Core 3.0眾多更新中,其中有一個(gè)重要的更新就是對(duì)gRPC的原生支持。從.NET Core3.0開始,無論是開發(fā)工具還是框架中,都與gRPC進(jìn)行了深度的集成,這讓使用gRPC的體驗(yàn)如絲般順滑。
“真的有這么絲滑嗎?
”2.1 工具
工具集成-絲滑享受,主要體現(xiàn)在msbuild,開發(fā)者可以直接使用宇宙第一IDE:Vistual Studio或者.NET Core SDK命令dotnet build,通過.proto文件去生成需要的gRPC服務(wù)端和客戶端代碼。這里有兩個(gè)必要條件:
安裝工具包
Google.Protobuf,Grpc.Tools
Install-Package?Google.Protobuf?-Version?3.12.2 Install-Package?Grpc.Tools?-Version?2.29.0.proto的引用
proto文件必須在.csproj中引用。在中使用標(biāo)簽。
<ItemGroup><Protobuf?Include="Protos\greet.proto"?GrpcServices="Client"?/><Protobuf?Include="Protos\greet.proto"?GrpcServices="Server"?/> </ItemGroup>其中GrpcServices屬性:指明生成的代碼是客戶端還是服務(wù)端,或者Both(這是默認(rèn)值)。當(dāng)編譯代碼時(shí)(無論是通過運(yùn)行Visual Studio的Build還是dotnet build),所有代碼都將生成并放在obj文件夾中。這是微軟故意這樣做的,因?yàn)檫@些代碼不應(yīng)該出現(xiàn)在源代碼控制存儲(chǔ)庫中,他們都是生成的,只要.proto文件在,他們都能隨時(shí)生成。
2.2 實(shí)際使用的技巧-親測(cè)有用
參考曉晨博客
主要目標(biāo)
讓客戶端和服務(wù)端共用一個(gè)Protos文件夾,避免重復(fù)
使用MSBuild變量在csproj中添加Protobuf標(biāo)簽,避免繁瑣修改csproj
服務(wù)端
?<ItemGroup><Protobuf?Include="..\Protos\*.proto"?GrpcServices="Server"?Link="Protos\%(RecursiveDir)%(Filename)%(Extension)"?/></ItemGroup>客戶端
??<ItemGroup><Protobuf?Include="..\Protos\*.proto"?GrpcServices="Client"?Link="Protos\%(RecursiveDir)%(Filename)%(Extension)"?/></ItemGroup>Include:加通配符的路徑,去指定proto文件的路徑
3.創(chuàng)建服務(wù)端
3.1 安裝包
創(chuàng)建gRPC服務(wù)端,需要包Grpc.AspNetCore
Install-Package?Grpc.AspNetCore?-Version?2.29.0很幸運(yùn),VS2019已經(jīng)為我們準(zhǔn)備好服務(wù)端的模板。我們可以創(chuàng)建一個(gè)gRPC服務(wù)端項(xiàng)目。這個(gè)模板已經(jīng)引入了Grpc.AspNetCore包。你可以在模板中搜到的。
3.2 引入proto文件
<ItemGroup><Protobuf?Include="Protos\greet.proto"?GrpcServices="Server"?/> </ItemGroup>當(dāng)然這,模板已經(jīng)為我們生成了。并且生成了GreeterService.cs
3.3 加入gRPC管道
gRPC添加到終結(jié)點(diǎn)路由中
ASP.NET Core 中間件和功能共享路由管道,因此可以將應(yīng)用配置為提供其他請(qǐng)求處理程序。其他請(qǐng)求處理程序與已配置的 gRPC 服務(wù)并行工作。
注冊(cè)服務(wù)
當(dāng)然這,模板已經(jīng)為我們生成了,不要模板自己刀耕火種也是可以的。
4.創(chuàng)建客戶端
4.1 安裝包
創(chuàng)建gRPC客戶端,需要包Google.Protobuf,Grpc.Tools,Grpc.Net.Client
Install-Package?Google.Protobuf?-Version?3.12.2 Install-Package?Grpc.Tools?-Version?2.29.0 Install-Package?Grpc.Net.Client?-Version?2.29.04.2 引入與服務(wù)端相同的proto文件
??<ItemGroup><Protobuf?Include="Protos\greet.proto"?GrpcServices="Client"?/></ItemGroup>4.3 編碼
static?async?Task?Main(string[]?args) {Console.WriteLine("Hello?gRPC!");AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport",?true);var?channel?=?GrpcChannel.ForAddress("https://localhost:5001");var?greeterClient?=?new?Greeter.GreeterClient(channel);//https://docs.microsoft.com/zh-cn/aspnet/core/grpc/troubleshoot?view=aspnetcore-3.0&WT.mc_id=DT-MVP-5003133var?reply?=?await?greeterClient.SayHelloAsync(new?HelloRequest{Name?=?"Garfield"});Console.WriteLine("Greeter?服務(wù)返回?cái)?shù)據(jù):?"?+?reply.Message);Console.ReadKey();//var?counterClient?=?new?Count.CounterClient(channel);This?switch?must?be?set?before?creating?the?GrpcChannel/HttpClient.//AppContext.SetSwitch(//????"System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport",?true);The?port?number(5000)?must?match?the?port?of?the?gRPC?server.//var?channel?=?GrpcChannel.ForAddress("http://localhost:5000");//var?client?=?new?Greet.GreeterClient(channel); }5.微服務(wù)中使用
如引言所述,gRPC主要用于微服務(wù)之間同步通信。
主要運(yùn)用場(chǎng)景,已經(jīng)根據(jù)業(yè)務(wù)劃分的多個(gè)微服務(wù)無法滿足實(shí)際出現(xiàn)的業(yè)務(wù)場(chǎng)景,需要聯(lián)合多個(gè)微服務(wù)進(jìn)行業(yè)務(wù)處理。沒錯(cuò),這就是微服務(wù)架構(gòu)體系中的自定義聚合器,實(shí)際上聚合器也是一種微服務(wù),負(fù)責(zé)聚合多個(gè)微服務(wù)提供較粒度更小的微服務(wù)更為強(qiáng)大的自定義微服務(wù)。至于使用方式,依然是引入Grpc.Net.Client包,此包本來就是HttpClient基礎(chǔ)上實(shí)現(xiàn)的,大可以把此當(dāng)作一個(gè)gPRC的HttpClient使用。
6.配置無TLS的gRPC
6.1 服務(wù)端配置
gRPC只支持HTTP/2。通常,當(dāng)客戶端連接到服務(wù)端時(shí),連接使用HTTP1.1完成,只有當(dāng)服務(wù)器和客戶端都支持HTTP/2時(shí)才提升為HTTP/2,這就是協(xié)議提升,實(shí)際上,同類似的, Websocket就是這樣通過http操作,走協(xié)議提升。這個(gè)協(xié)議提升使用協(xié)議協(xié)商執(zhí)行,通常需要使用ALPN協(xié)議實(shí)現(xiàn),這個(gè)協(xié)議要求必須TLS。
這意味著,在默認(rèn)情況下,您需要啟用一個(gè)TLS端點(diǎn),以便能夠使用gRPC。
但是,這里有一個(gè)但是,在內(nèi)部的微服務(wù)中,可能是沒有啟用TLS的,也沒必要,因?yàn)榇蠹叶际亲约喝?#xff0c;取消TLS,提高效率。在這種情況下,你有兩個(gè)選擇:
打開一個(gè)Kestrel,監(jiān)聽HTTP/2
打開兩個(gè)Kestrel,一個(gè)監(jiān)聽HTTP1.1,另一個(gè)監(jiān)聽HTTP/2
如果您的服務(wù)器除了支持gRPC客戶端還必須支持HTTP1.1客戶端,則需要第二個(gè)選項(xiàng)。下面的代碼就是展示了第二種方法(Program.cs):
WebHost.CreateDefaultBuilder(args).ConfigureKestrel(options?=>{options.Listen(IPAddress.Any,?5000,?listenOptions?=>{listenOptions.Protocols?=?HttpProtocols.Http1AndHttp2;});//Setup?a?HTTP/2?endpoint?without?TLS.options.Listen(IPAddress.Any,?5001,?listenOptions?=>{listenOptions.Protocols?=?HttpProtocols.Http2;});})5000:提供http web api
5001:提供gRPC
6.2 在.NET Core客戶端調(diào)用
但是,這還不夠,我們需要告訴gRPC客戶端,客戶端可以直接連接到HTTP/2端點(diǎn),而不需要TLS,口頭或者文檔說明。
在默認(rèn)情況下.NET Core不允許gRPC客戶端連接到非TLS(non-TLS)端點(diǎn)-不安全的gRPC的服務(wù),十有八九都會(huì)報(bào)異常
Unhandled?exception.?System.Net.Http.HttpRequestException:?The?SSL?connection?could?not?be?established,?see?inner?exception.?--->?System.Security.Authentication.AuthenticationException:?The?remote?certificate?is?invalid?according?to?the?validation?procedure.那么怎么辦,就需要如下代碼:
//?This?switch?must?be?set?before?creating?the?GrpcChannel/HttpClient. AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport",?true);//?The?port?number(5000)?must?match?the?port?of?the?gRPC?server. var?channel?=?GrpcChannel.ForAddress("http://localhost:5000"); var?client?=?new?Greet.GreeterClient(channel);上述設(shè)置只能在客戶端開始時(shí)設(shè)置一次。
7.配置TLS的gRPC
毫無疑問,微服務(wù)場(chǎng)景之外的gRPC服務(wù)還是需要TLS的。
7.1 方法一:appsetting.json
{"Kestrel":?{"Endpoints":?{"HttpsInlineCertFile":?{"Url":?"https://localhost:5001","Protocols":?"Http2","Certificate":?{"Path":?"<path?to?.pfx?file>","Password":?"<certificate?password>"}}}} }7.2 方法二:Program.cs
public?static?IHostBuilder?CreateHostBuilder(string[]?args)?=>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder?=>{webBuilder.ConfigureKestrel(options?=>{options.Listen(IPAddress.Any,?5001,?listenOptions?=>{listenOptions.Protocols?=?HttpProtocols.Http2;listenOptions.UseHttps("<path?to?.pfx?file>",?"<certificate?password>");});});webBuilder.UseStartup<Startup>();});8.寫在末尾
Azure App Service 和IIS目前都還不支持gRPC. ?另外Http.Sys也不支持gRPC所依賴的HTTP響應(yīng)。詳情請(qǐng)看github issues
參考鏈接
https://grpc.io/
https://www.cnblogs.com/shanyou/p/3452938.html
https://blog.csdn.net/yangguosb/article/details/80592777
https://docs.microsoft.com/zh-cn/aspnet/core/grpc/aspnetcore?view=aspnetcore-3.1&tabs=visual-studio
https://docs.microsoft.com/zh-cn/aspnet/core/grpc/troubleshoot?view=aspnetcore-3.1
https://www.cnblogs.com/stulzq/p/11581967.html
總結(jié)
以上是生活随笔為你收集整理的【gRPC】 在.Net core中使用gRPC的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 整合.NET WebAPI和 Vuejs
- 下一篇: AgileConfig-如何使用Agil