亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

.NET Core中使用gRPC的方法

瀏覽:162日期:2022-06-08 10:55:41
目錄
  • 1.什么是gRPC
    • 1.基本介紹
    • 2.proto文件
    • 3.上手實(shí)踐
  • 2.gRPC流
    • 1.服務(wù)端流、客戶端流、雙向流
    • 2.NetCore Web項(xiàng)目作為客戶端
  • 3.gRPC AOP攔截

    1.什么是gRPC

    1.基本介紹

    gRPC 一開(kāi)始由 google 開(kāi)發(fā),是一款語(yǔ)言中立、平臺(tái)中立、開(kāi)源的遠(yuǎn)程過(guò)程調(diào)用(RPC)系統(tǒng),所以叫g(shù)(google)RPC。支持主流開(kāi)發(fā)語(yǔ)言(C, C++, Python, PHP, Ruby, NodeJS, C#, Objective-C、Golang

    2.proto文件

    用于定義協(xié)議接口和數(shù)據(jù)格式,不同的語(yǔ)言,相同的文件,可以理解為一項(xiàng)約定,序列化支持 PB(Protocol buffer)和 JSON,PB 是一種語(yǔ)言無(wú)關(guān)的高性能序列化框架,基于 HTTP/2 + PB, 保障了 RPC 調(diào)用的高性能。

    說(shuō)這么多感覺(jué)還是很模糊,上面只是介紹了gRPC是什么,在我看來(lái)其實(shí)它大致的作用跟WebServicesWCF差不多,在某個(gè)維度上可以說(shuō)都是作為遠(yuǎn)程調(diào)用,只不過(guò)所處的時(shí)代和本身的特性,以及生態(tài)的發(fā)展下,導(dǎo)致它成為目前比較火熱的原因之一,具體的內(nèi)容后面再討論,先用起來(lái),再深入了解,接下來(lái)我們使用.Net Core 先搭建一個(gè)簡(jiǎn)單的Demo,來(lái)親自上手實(shí)踐一下。

    其實(shí)背景就是最近在做一個(gè)項(xiàng)目,需要做一個(gè)公司內(nèi)部的Nuget包,大概的業(yè)務(wù)就是Nuget包請(qǐng)求微服務(wù)數(shù)據(jù),開(kāi)始想直接使用http的方式,基于整體項(xiàng)目結(jié)構(gòu)后面定了使用gRPC,既學(xué)即用,剛好也可以在實(shí)際項(xiàng)目應(yīng)用中,查漏補(bǔ)缺。

    3.上手實(shí)踐

    1.使用vs首先創(chuàng)建一個(gè)NetCore gRPC項(xiàng)目,得到一個(gè)項(xiàng)目結(jié)構(gòu)如下,框架默認(rèn)包含一個(gè)已經(jīng)預(yù)先定義協(xié)議文件服務(wù)接口,如果使用其他的方式也很簡(jiǎn)單直接引用相關(guān)的包,然后添加以下服務(wù)就可以了

    2.我們自己創(chuàng)建一個(gè)自己的接口,定義一個(gè)協(xié)議文件mytestdemo.proto,然后定義一些方法,主要包含如下幾類,其他的一些用法可以在網(wǎng)上搜到,或者去看文檔,只是簡(jiǎn)單列一下

    1.有參數(shù)有返回值

    2.無(wú)參數(shù)有返回值 ,無(wú)參使用google.protobuf.Empty

    3.集合作為返回值,必須使用repeated 標(biāo)記

    如果你真的不熟悉protobuf的定義方式和寫法,這個(gè)無(wú)傷大雅,可以使用工具生成

    syntax = "proto3";//引入集合包import "google/protobuf/empty.proto";//命名空間option csharp_namespace = "GrpcDemo";//包名package MyTest;//接口定義service MyTestDemo {  rpc MultipleParam(MultipleRequestPara) returns (MultipleRespone);  rpc NoParam(google.protobuf.Empty) returns (SingeRespone);  rpc CollectionParam(google.protobuf.Empty) returns (CollectionResponePara);}//多參數(shù)請(qǐng)求參數(shù)message MultipleRequestPara {  int32 Id = 1;  string Name = 2;//參數(shù)個(gè)數(shù)  bool IsExists =3;}message SingeRespone {  bool Success =1;  TestEntity a1 = 2;  message TestEntity{	int32 Id =1;  }}//多參數(shù)返回message MultipleRespone {	bool Success =1;}//返回集合參數(shù)message CollectionResponePara {	repeated CollectionChildrenRespone1 param1 =1;	repeated CollectionChildrenRespone2 param2 =2;	repeated int32 param3 =3;}//集合屬性1message CollectionChildrenRespone1 {	int32 Id =1;}//集合屬性2message CollectionChildrenRespone2 {	string Name =1;	}

    3.右鍵類,選擇添加,選擇連接的服務(wù),添加gRPC,或者直接修改項(xiàng)目文件,將新建的proto添加到類中

    3.1 重新生成,然后創(chuàng)建服務(wù)代碼MyTestService,如下代碼
    3.2 在啟動(dòng)類中映射gRPC app.MapGrpcService<MyTestService>(); 否則會(huì)報(bào)service is unimplemented.

    /// <summary>/// 繼承自MyTestDemo.MyTestDemoBase/// </summary>public class MyTestService : MyTestDemo.MyTestDemoBase{    public override async Task<MultipleRespone> MultipleParam(MultipleRequestPara request, ServerCallContext context)    {return await Task.FromResult(new MultipleRespone{    Success = true,});    }    public override async Task<SingeRespone> NoParam(Empty request, ServerCallContext context)    {       TestEntity t = new TestEntity();       t.Id = 1;       return await Task.FromResult(new SingeRespone { Success = true, entity = t  }); ;    }    public override async Task<CollectionResponePara> CollectionParam(Empty request, ServerCallContext context)    {CollectionResponePara collectionResponePara = new CollectionResponePara();CollectionChildrenRespone1 a = new CollectionChildrenRespone1 { Id = 1 };CollectionChildrenRespone2 b = new CollectionChildrenRespone2 { Name = "jeck" };collectionResponePara.Param1.Add(a);collectionResponePara.Param2.Add(b);return  await  Task.FromResult(collectionResponePara);    }}

    4.創(chuàng)建客戶端,將proto文件拷貝過(guò)去調(diào)用,添加服務(wù)為客戶端模式,然后添加如下代碼

    using (var channel = GrpcChannel.ForAddress("https://localhost:7245")) {     var client =  new MyTestDemo.MyTestDemoClient(channel);     //多參數(shù)調(diào)用     var reply = client.MultipleParam(new MultipleRequestPara { Id = 123, Name = "sa", IsExists = true });       //無(wú)參調(diào)用     var singeRespone = client.NoParam(new Google.Protobuf.WellKnownTypes.Empty());     //調(diào)用集合     var collectionResponePara = client.CollectionParam(new Google.Protobuf.WellKnownTypes.Empty()); }

    2.gRPC流

    gRPC中支持4種流,分別是:

    1.簡(jiǎn)單 RPC(Unary RPC)它的特點(diǎn)是傳入一個(gè)請(qǐng)求對(duì)象,返回一個(gè)請(qǐng)求對(duì)象

    2.服務(wù)端流式 RPC (Server streaming RPC)客戶端傳入一個(gè)請(qǐng)求對(duì)象,服務(wù)端可以返回多個(gè)結(jié)果對(duì)象,形象的表示就是客戶端傳入一個(gè)股票的id,服務(wù)端就將股票的信息遠(yuǎn)遠(yuǎn)不斷地返回

    3.客戶端流式 RPC (Client streaming RPC) 客戶端源源不斷的傳入多個(gè)請(qǐng)求對(duì)象,服務(wù)端返回一個(gè)結(jié)果對(duì)象,形象的表示例如上位機(jī)采集實(shí)時(shí)將采集數(shù)據(jù),源源不斷的傳入服務(wù)器

    4.雙向流式 RPC (Bi-directional streaming RPC) 結(jié)合服務(wù)端和客戶端流,傳入多請(qǐng)求,返回多個(gè)結(jié)果,相當(dāng)于建立長(zhǎng)連接,可以進(jìn)行相互的操作

    下面我們就主要介紹幾類主要的流的使用以及步驟

    1.服務(wù)端流、客戶端流、雙向流

    服務(wù)端流主要的特征就是服務(wù)端會(huì)源源不斷的響應(yīng)數(shù)據(jù)到客戶端

    1.首先還是創(chuàng)建protobuf文件,聲明一個(gè)服務(wù)端流的rpc接口ExcuteServerStream 和一個(gè)客戶端流接口ExcuteClientStream

    syntax = "proto3";option csharp_namespace = "GrpcDemo";package streamtest;service StreamTest {  //服務(wù)端流定義  rpc ExcuteServerStream(StreamForClientRequest) returns (stream StreamForClientRespones);  //客戶端流定義  rpc ExcuteServerStream(StreamForClientRequest) returns (stream StreamForClientRespones);  //雙向流  rpc ExcuteMutualStream(stream StreamForClientRequest) returns ( stream StreamForClientRespones);}//調(diào)用流的請(qǐng)求對(duì)象message StreamForClientRequest{    int32 Id=1;}//調(diào)用端流的返回對(duì)象message StreamForClientRespones{	repeated int32 Number=1;//集合}

    2.重新生成服務(wù)引用,然后創(chuàng)建對(duì)應(yīng)的實(shí)現(xiàn)接口StreamTestService并重寫生成的服務(wù),然后在啟動(dòng)程序映射服務(wù)接口

    //服務(wù)端流接口public override async Task ExcuteServerStream(StreamForClientRequest req,IServerStreamWriter<StreamForClientRespones> resStream,ServerCallContext context){    //list集合作為模擬數(shù)據(jù)源    var list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };    foreach (var item in list)    {Console.WriteLine($"********{item}*******");var ele = new StreamForClientRespones();ele.Number.Add(item);//寫入流中await resStream.WriteAsync(ele);//模擬源源不斷的數(shù)據(jù)響應(yīng)await Task.Delay(1000);    }}//客戶端流接口public override async Task<StreamForClientRespones> ExcuteClientStream( IAsyncStreamReader<StreamForClientRequest> requestStream, ServerCallContext context){    StreamForClientRespones intArrayModel = new StreamForClientRespones();    //獲取請(qǐng)求流中的數(shù)據(jù)    while (await requestStream.MoveNext())    {intArrayModel.Number.Add(requestStream.Current.Id + 1);Console.WriteLine($"ExcuteClientStream Number {requestStream.Current.Id} 獲取到并處理.");Thread.Sleep(100);    }    return intArrayModel;}//雙向流public override async Task ExcuteMutualStream(IAsyncStreamReader<StreamForClientRequest> reqStream,IServerStreamWriter<StreamForClientRespones> resStream,ServerCallContext context){    int i = 0;    //從流中獲取請(qǐng)求    while (await reqStream.MoveNext())    {i++;var ele = new StreamForClientRespones();ele.Number.Add(i);//寫入響應(yīng)流await resStream.WriteAsync(ele);await Task.Delay(500);    }}

    3.創(chuàng)建客戶端調(diào)用,把服務(wù)端的protobuf文件拷貝到客戶端,然后生成,啟動(dòng)調(diào)用

    //調(diào)用服務(wù)端流 using (var channel = GrpcChannel.ForAddress("https://localhost:7245")) {     var client = new StreamTest.StreamTestClient(channel);     //調(diào)用服務(wù)端流     var reply =  client.ExcuteServerStream(new StreamForClientRequest { Id =1});     //利用線程取消     //CancellationTokenSource cts = new CancellationTokenSource();     //指定在2s后進(jìn)行取消操作     //cts.CancelAfter(TimeSpan.FromSeconds(2.5));      //var reply = client.ExcuteServerStream(new StreamForClientRequest { Id = 1 }, cancellationToken: cts.Token);     await foreach (var resp in reply.ResponseStream.ReadAllAsync())     { Console.WriteLine(resp.Number[0]);     } } //調(diào)用客戶端流 using (var channel = GrpcChannel.ForAddress("https://localhost:7245")) {     var client = new StreamTest.StreamTestClient(channel);     //調(diào)用客戶端流接口     var reply = client.ExcuteClientStream();     //模擬源源不斷的數(shù)據(jù)發(fā)送     for (int i = 0; i < 10; i++)     { await reply.RequestStream.WriteAsync(new StreamForClientRequest() { Id = new Random().Next(0, 20) }); await Task.Delay(100);     }     Console.WriteLine("*************發(fā)送完畢*******************");     await reply.RequestStream.CompleteAsync();     //接受結(jié)果     foreach (var item in reply.ResponseAsync.Result.Number)     { Console.WriteLine($"This is {item} Result");     } }//雙向流using (var channel = GrpcChannel.ForAddress("https://localhost:7245")){    var client = new StreamTest.StreamTestClient(channel);    //調(diào)用雙向流接口    var reply = client.ExcuteMutualStream();    //獲取流放入線程    var bathCatRespTask = Task.Run(async () =>    {await foreach (var resp in reply.ResponseStream.ReadAllAsync()){    Console.WriteLine(resp.Number[0]);}    });    //寫入流    for (int i = 0; i < 10; i++)    {await reply.RequestStream.WriteAsync(new StreamForClientRequest() { Id = new Random().Next(0, 20) });await Task.Delay(100);    }    //發(fā)送完畢    await reply.RequestStream.CompleteAsync();    //開(kāi)始接收響應(yīng)    await bathCatRespTask;}

    2.NetCore Web項(xiàng)目作為客戶端

    1.首先還是先引入proto文件,然后生成客戶端

    2.在web項(xiàng)目中的控制器中,我們就不能直接簡(jiǎn)陋的使用 using的方式來(lái)連接gRPC服務(wù)端了,可以利用內(nèi)置的依賴注入的模式來(lái)完成

    3.下載Grpc.Net.ClientFactory包,然后在`Program將客戶端添加到依賴注入容器

    builder.Services.AddGrpcClient<MyTestDemo.MyTestDemoClient>(option => {    option.Address = new Uri("https://localhost:7245");});

    4.然后在控制器中直接注入,就可以使用

     public class gRPCTestController : ControllerBase {     private readonly MyTestDemoClient _client;     public gRPCTestController(MyTestDemoClient client)     { _client = client;     }     [HttpGet(Name = "Excute")]     public async Task<string> Get()     { var a = await _client.NoParamAsync(new Google.Protobuf.WellKnownTypes.Empty()); var str = a.Success.ToString(); return str;     } }

    5.調(diào)用出現(xiàn)如下問(wèn)題 ,使用dotnet dev-certs https --trust

    3.gRPC AOP攔截

    有時(shí)候我們想在gRPC服務(wù)執(zhí)行前后做一些操作,這時(shí)候可以使用其Aop攔截,如果你要問(wèn)攔截器可以做什么,我不太想解釋,繼續(xù)往下看,攔截器方法定義在Interceptor類中,服務(wù)端和客戶端攔截是一樣的原理,下面列舉一些攔截器:

    名稱特點(diǎn)BlockingUnaryCall攔截阻塞調(diào)用AsyncUnaryCall攔截異步調(diào)用AsyncServerStreamingCall攔截異步服務(wù)端流調(diào)用AsyncClientStreamingCall攔截異步客戶端流調(diào)用AsyncDuplexStreamingCall攔截異步雙向流調(diào)用UnaryServerHandler用于攔截和傳入普通調(diào)用的服務(wù)器端處理程序ClientStreamingSerHandler用于攔截客戶端流調(diào)用的服務(wù)器端處理程序ServerStreamingSerHandler用于攔截服務(wù)端流調(diào)用的服務(wù)器端處理程序DuplexStreamingSerHandler用于攔截雙向流調(diào)用的服務(wù)器端處理程序

    1.聲明一個(gè)UnaryServerHandlerInterceptor類型的自定義攔截器,用于攔截和傳入普通調(diào)用的服務(wù)器端處理程序,然后繼承自Grpc.Core.Interceptors.Interceptor類, 重寫已經(jīng)定義的方法UnaryServerHandler

    public class UnaryServerHandlerInterceptor : Interceptor{    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(       TRequest request,       ServerCallContext context,       UnaryServerMethod<TRequest, TResponse> continuation)    {Console.WriteLine("執(zhí)行調(diào)用前");var result = await continuation(request, context);Console.WriteLine("執(zhí)行調(diào)用后");// 或向 客戶端附加 一些信息// 也可以 用try catch 做異常日志// 可以從 context中取出 調(diào)用方ip,做ip限制// 可以 監(jiān)控continuation 的 執(zhí)行時(shí)間return result;    } }

    2.然后在注入容器時(shí)加入選項(xiàng)

    builder.Services.AddGrpc(option => {     option.EnableDetailedErrors = true;    //加入服務(wù)端攔截器選項(xiàng)    option.Interceptors.Add<UnaryServerHandlerInterceptor>();});

    到此這篇關(guān)于.NET Core中使用gRPC的文章就介紹到這了,更多相關(guān).NET Core使用gRPC內(nèi)容請(qǐng)搜索以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持!

    標(biāo)簽: ASP.NET
    主站蜘蛛池模板: 手机看片自拍自拍自拍 | 国产在线精品成人一区二区三区 | 免费看黄网站大全 | 欧美日韩免费大片 | 久久va| 国产亚洲精品一区二区三区 | 国产永久免费视频m3u8 | 国产欧美亚洲精品第一页青草 | 欧美日韩综合 | 久久成人精品视频 | 妞干网在线视频观看 | 2021国产精品一区二区在线 | 日本不卡毛片一二三四 | 亚洲欧美日韩国产色另类 | 9999网站| 欧美国产精品久久 | 在线观看免费黄网站 | 天天干成人网 | 国产精品一区在线播放 | 日本高清中文字幕视频在线 | 精品国产91久久久久 | 成人免费视频在 | 黄色国产大片 | aaaa级毛片欧美的 | 99ri国产在线观看 | a免费网站| 国产1024在线永久免费观看 | 国产一区二区三区在线电影 | 亚洲综合狠狠 | 久夜色精品国产一区二区三区 | 国产在线色视频 | 亚洲欧美在线视频免费 | 欧美成人午夜毛片免费影院 | 亚洲一区二区视频在线观看 | 91插插插视频 | 国产成人精品久久免费动漫 | 91正在播放极品白嫩在线观看 | 久久久久夜色精品波多野结衣 | 精品综合| 久操免费在线观看 | 在线观看91香蕉国产免费 |