日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

gRPC-微服务间通信实践

發(fā)布時(shí)間:2023/12/4 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 gRPC-微服务间通信实践 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

微服務(wù)間通信常見(jiàn)的兩種方式

由于微服務(wù)架構(gòu)慢慢被更多人使用后,迎面而來(lái)的問(wèn)題是如何做好微服務(wù)間通信的方案。我們先分析下目前最常用的兩種服務(wù)間通信方案。

  • gRPC(rpc遠(yuǎn)程調(diào)用)

場(chǎng)景:A服務(wù)主動(dòng)發(fā)起請(qǐng)求到B服務(wù),同步方式
范圍:只在微服務(wù)間通信應(yīng)用

  • EventBus(基于消息隊(duì)列的集成事件)

技術(shù):NotNetCore.Cap + Rabbitmq + Database
場(chǎng)景:A服務(wù)要在B服務(wù)做某件事情后響應(yīng),異步方式
實(shí)現(xiàn):B服務(wù)在完成某件事情后發(fā)布消息,A服務(wù)訂閱此消息
范圍:只在微服務(wù)間通信應(yīng)用

通過(guò)對(duì)比,兩種方式完全不一樣。rpc是類(lèi)似于http請(qǐng)求的及時(shí)響應(yīng)機(jī)制,但是比http更輕量、快捷,它更像以前的微軟的WCF,可以自動(dòng)生成客戶(hù)端代碼,充分體現(xiàn)了面向?qū)嶓w對(duì)象的遠(yuǎn)程調(diào)用的思想;Eventbus是異步的消息機(jī)制,基于cap的思想,不關(guān)心下游訂閱方服務(wù)是否消費(fèi)成功,保障了主服務(wù)業(yè)務(wù)的流暢性,同時(shí)也是一款分布式事務(wù)的實(shí)現(xiàn)方案,可以保障分布式架構(gòu)中的數(shù)據(jù)的最終一致性。

我們今天主要介紹gRPC在微服務(wù)中的實(shí)踐案例。

gRPC-Server(服務(wù)端)

框架介紹

  • .Net Core sdk 3.1

  • Grpc.AspNetCore 2.30.0

  • Grpc.Core 2.30.0

搭建步驟

以.net core webapi 項(xiàng)目為例,詳細(xì)說(shuō)明如何集成gRPC。

創(chuàng)建項(xiàng)目

創(chuàng)建web api項(xiàng)目,此步驟說(shuō)明省略

引入nuget包

引入gRPC 服務(wù)端需要的 nuget包,Grpc.AspNetCore 2.30.0和Grpc.Core 2.30.0

外部訪問(wèn)

考慮到項(xiàng)目發(fā)布后,有webapi本身的http的接口和gRPC的接口都要給外部訪問(wèn),就需要暴露http1和http2兩個(gè)端口。

方式1:本地調(diào)試時(shí),可以直接暴露http和https,如果你的服務(wù)器支持https,也可以在生產(chǎn)環(huán)境使用https來(lái)訪問(wèn)gRPC服務(wù)。

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().UseNLog().UseUrls("http://*:5000;https://*:5001");

方式2:如果在容器化部署場(chǎng)景下,一般會(huì)在dockerfile中指定ASPNETCORE_PORT環(huán)境變量,然后程序監(jiān)聽(tīng)http1和http2兩個(gè)端口。

public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{var aspnetcorePort = Environment.GetEnvironmentVariable("ASPNETCORE_PORT") ?? 5000;int.TryParse(aspnetcorePort, out int port);webBuilder.ConfigureKestrel(options =>{options.ListenAnyIP(port, options => options.Protocols = HttpProtocols.Http1);options.ListenAnyIP(port + 1, options => options.Protocols = HttpProtocols.Http2);}).UseStartup<Startup>();webBuilder.UseNLog();});

異常處理

由于gRPC服務(wù)端只能throw 基于 Grpc.Core.RpcException 的異常類(lèi)型,所以我們可以自定義中間件來(lái)統(tǒng)一處理下異常

using Grpc.Core; using Grpc.Core.Interceptors; using System; using System.Threading.Tasks;public class ExceptionInterceptor : Interceptor{public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request,ServerCallContext context,UnaryServerMethod<TRequest, TResponse> continuation){try{return await continuation(request, context);}catch (RpcException ex){throw ex;}catch (Exception ex){throw new RpcException(new Status(StatusCode.Internal, ex.Message + "\r\n" + ex.StackTrace));}}}

代碼中被繼承的 Interceptor 是 Grpc.Core.Interceptors.Interceptor。主要處理的目的是把在gRPC接口中拋出的非 RpcException 的異常,轉(zhuǎn)換為 RpcException。此中間件也是根據(jù)具體的業(yè)務(wù)需求來(lái)做的,主要是告訴大家可以重寫(xiě) Grpc.Core.Interceptors.Interceptor 的攔截器來(lái)統(tǒng)一處理一些事情。

定義協(xié)議緩沖區(qū)(protocol3)

新建項(xiàng)搜索rpc可以出現(xiàn)協(xié)議緩沖區(qū)文件

定義示例接口,創(chuàng)建訂單方法,以及創(chuàng)建訂單入?yún)⒑统鰠?。關(guān)于proto3協(xié)議具體說(shuō)明,請(qǐng)參考往期文章。

syntax = "proto3";option csharp_namespace = "GrpcTest.Protos";service Order {rpc CreateOrder (CreateOrderRequest) returns (CreateOrderReply); }message CreateOrderRequest {string ItemCode = 1;string ItemName = 2;string Spec = 3;double Price = 4;double Quantity = 5;string Unit = 6;double Cost = 7; }message CreateOrderReply {bool success = 1; }

在項(xiàng)目的csproj文件中,需要有proto包含進(jìn)去,GrpcServices="Server"表示當(dāng)前是服務(wù)端。改好后重新生成下項(xiàng)目。

<ItemGroup><Protobuf Include="Protos/GrpcTest.Protos" GrpcServices="Server" /></ItemGroup>

創(chuàng)建OrderService

手動(dòng)創(chuàng)建OrderService,繼承自O(shè)rder.OrderBase(proto自動(dòng)生成的代碼)

public class OrderService : Order.OrderBase{public async override Task<CreateOrderReply> CreateOrder(CreateOrderRequest request, ServerCallContext context){//todo something//throw RpcException異常throw new RpcException(new Status(StatusCode.NotFound, "資源不存在"));//返回return new CreateOrderReply{Success = true};}}

重寫(xiě)CreateOrder方法,此處就可以寫(xiě)你的實(shí)際的業(yè)務(wù)代碼,相當(dāng)于Controller接口入口。如果業(yè)務(wù)中需要主動(dòng)拋出異常,可以使用RpcException,有定義好的一套狀態(tài)碼和異常封裝。

修改Startup

在ConfigureServices方法中加入AddGrpc,以及上面提到的異常處理中間件,代碼如下

services.AddGrpc(option => option.Interceptors.Add<ExceptionInterceptor>());

在Configure方法中將OrderService啟用,代碼如下

app.UseEndpoints(endpoints =>{endpoints.MapGrpcService<OrderService>();endpoints.MapGet("/", async context =>{await context.Response.WriteAsync("this is a gRPC server");});});

至此 gRPC服務(wù)端搭建完成。

gRPC-Client(客戶(hù)端)

框架介紹

  • .Net Core sdk 3.1

  • Google.Protobuf 3.12.4

  • Grpc.Tools 2.30.0

  • Grpc.Net.ClientFactory 2.30.0

搭建步驟

以.net core webapi 項(xiàng)目為例,詳細(xì)說(shuō)明如何集成gRPC客戶(hù)端

創(chuàng)建項(xiàng)目

創(chuàng)建web api項(xiàng)目,此步驟說(shuō)明省略

引入nuget包

引入gRPC 客戶(hù)端需要的 nuget包,Google.Protobuf 3.12.4、Grpc.Tools 2.30.0和Grpc.Net.ClientFactory 2.30.0

引入proto文件

將服務(wù)端的 order.proto 拷貝到客戶(hù)端的web api項(xiàng)目中,并在csproj文件中添加ItemGroup節(jié)點(diǎn)。GrpcServices="Client"表示當(dāng)前是客戶(hù)端。改好后重新生成下項(xiàng)目。

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

修改Startup

在ConfigureServices方法中加入AddGrpcClient,代碼如下

services.AddHttpContextAccessor();AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);var baseUrl = "http://localhost:5001/";services.AddGrpcClient<Order.OrderClient>(options =>{options.Address = new Uri(baseUrl);});

注意:要使用.NET Core客戶(hù)端調(diào)用不安全的gRPC服務(wù),需要進(jìn)行其他配置。gRPC客戶(hù)端必須將System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport開(kāi)關(guān)設(shè)置為true,并在服務(wù)器地址中使用http。可以在以下鏈接查看具體說(shuō)明。

[Troubleshoot gRPC on .NET Core]

另外說(shuō)明下services.AddGrpcClient方法,來(lái)自于nuget包Grpc.Net.ClientFactory 2.30.0,將gRPC客戶(hù)端的注入封裝,具體代碼實(shí)現(xiàn)可以查看以下鏈接。

Grpc.Net.ClientFactory

客戶(hù)端調(diào)用

以在Controller中調(diào)用為例,示例代碼如下

[ApiController][Route("[controller]")]public class WeatherForecastController : ControllerBase{private readonly Order.OrderClient _orderClient;public WeatherForecastController(Order.OrderClient orderClient){_orderClient = orderClient;}[HttpGet]public async Task<IEnumerable<WeatherForecast>> Get(){var result = await _orderClient.CreateOrderAsync(new CreateOrderRequest{ItemCode = "123",ItemName = "名稱(chēng)1"});}}

通過(guò)構(gòu)造函數(shù)注入gRPC客戶(hù)端,然后就可以使用里面的同步或者異步方法啦!

總結(jié)

以上是生活随笔為你收集整理的gRPC-微服务间通信实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。