广告
返回顶部
首页 > 资讯 > 后端开发 > ASP.NET >.NET Core中使用gRPC的方法
  • 284
分享到

.NET Core中使用gRPC的方法

2024-04-02 19:04:59 284人浏览 薄情痞子
摘要

目录1.什么是grpc1.基本介绍2.proto文件3.上手实践2.grpc流1.服务端流、客户端流、双向流2.netcore WEB项目作为客户端3.gRPC aop拦截1.什么是

1.什么是gRPC

1.基本介绍

gRPC 一开始由 Google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统,所以叫g(google)RPC。支持主流开发语言(C, c++, python, PHP, Ruby, nodejs, C#, Objective-C、golang

2.proto文件

用于定义协议接口和数据格式,不同的语言,相同的文件,可以理解为一项约定,序列化支持 PB(Protocol buffer)和 JSON,PB 是一种语言无关的高性能序列化框架,基于 Http/2 + PB, 保障了 RPC 调用的高性能。

说这么多感觉还是很模糊,上面只是介绍了gRPC是什么,在我看来其实它大致的作用跟WebServicesWCF差不多,在某个维度上可以说都是作为远程调用,只不过所处的时代和本身的特性,以及生态的发展下,导致它成为目前比较火热的原因之一,具体的内容后面再讨论,先用起来,再深入了解,接下来我们使用.net core 先搭建一个简单的Demo,来亲自上手实践一下。

其实背景就是最近在做一个项目,需要做一个公司内部的Nuget包,大概的业务就是Nuget包请求微服务数据,开始想直接使用http的方式,基于整体项目结构后面定了使用gRPC,既学即用,刚好也可以在实际项目应用中,查漏补缺。

3.上手实践

1.使用vs首先创建一个netcore gRPC项目,得到一个项目结构如下,框架默认包含一个已经预先定义协议文件服务接口,如果使用其他的方式也很简单直接引用相关的包,然后添加以下服务就可以了

2.我们自己创建一个自己的接口,定义一个协议文件mytestdemo.proto,然后定义一些方法,主要包含如下几类,其他的一些用法可以在网上搜到,或者去看文档,只是简单列一下

1.有参数有返回值

2.无参数有返回值 ,无参使用google.protobuf.Empty

3.集合作为返回值,必须使用repeated 标记

如果你真的不熟悉protobuf的定义方式和写法,这个无伤大雅,可以使用工具生成

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);
}

//多参数请求参数
message MultipleRequestPara {
  int32 Id = 1;
  string Name = 2;//参数个数
  bool IsExists =3;
}
message SingeRespone {
  bool Success =1;
  TestEntity a1 = 2;
  message TestEntity{
	int32 Id =1;
  }
}
//多参数返回
message MultipleRespone {
	bool Success =1;
}
//返回集合参数
message CollectionResponePara {
	repeated CollectionChildrenRespone1 param1 =1;
	repeated CollectionChildrenRespone2 param2 =2;
	repeated int32 param3 =3;
}
//集合属性1
message CollectionChildrenRespone1 {
	int32 Id =1;
}
//集合属性2
message CollectionChildrenRespone2 {
	string Name =1;	
}

3.右键类,选择添加,选择连接的服务,添加gRPC,或者直接修改项目文件,将新建的proto添加到类中

3.1 重新生成,然后创建服务代码MyTestService,如下代码
3.2 在启动类中映射gRPC app.MapGrpcService<MyTestService>(); 否则会报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.创建客户端,将proto文件拷贝过去调用,添加服务为客户端模式,然后添加如下代码

using (var channel = GrpcChannel.ForAddress("https://localhost:7245"))
 {
     var client =  new MyTestDemo.MyTestDemoClient(channel);
     //多参数调用
     var reply = client.MultipleParam(new MultipleRequestPara { Id = 123, Name = "sa", IsExists = true });  
     //无参调用
     var singeRespone = client.NoParam(new Google.Protobuf.WellKnownTypes.Empty());
     //调用集合
     var collectionResponePara = client.CollectionParam(new Google.Protobuf.WellKnownTypes.Empty());
 }

2.gRPC流

gRPC中支持4种流,分别是:

1.简单 RPC(Unary RPC)它的特点是传入一个请求对象,返回一个请求对象

2.服务端流式 RPC (Server streaming RPC)客户端传入一个请求对象,服务端可以返回多个结果对象,形象的表示就是客户端传入一个股票的id,服务端就将股票的信息远远不断地返回

3.客户端流式 RPC (Client streaming RPC) 客户端源源不断的传入多个请求对象,服务端返回一个结果对象,形象的表示例如上位机采集实时将采集数据,源源不断的传入服务器

4.双向流式 RPC (Bi-directional streaming RPC) 结合服务端和客户端流,传入多请求,返回多个结果,相当于建立长连接,可以进行相互的操作

下面我们就主要介绍几类主要的流的使用以及步骤

1.服务端流、客户端流、双向流

服务端流主要的特征就是服务端会源源不断的响应数据到客户端

1.首先还是创建protobuf文件,声明一个服务端流的rpc接口ExcuteServerStream 和一个客户端流接口ExcuteClientStream

syntax = "proto3";
option csharp_namespace = "GrpcDemo";
package streamtest;

service StreamTest {
  //服务端流定义
  rpc ExcuteServerStream(StreamForClientRequest) returns (stream StreamForClientRespones);
  //客户端流定义
  rpc ExcuteServerStream(StreamForClientRequest) returns (stream StreamForClientRespones);
  //双向流
  rpc ExcuteMutualStream(stream StreamForClientRequest) returns ( stream StreamForClientRespones);
}

//调用流的请求对象
message StreamForClientRequest{
    int32 Id=1;
}

//调用端流的返回对象
message StreamForClientRespones{
	repeated int32 Number=1;//集合
}

2.重新生成服务引用,然后创建对应的实现接口StreamTestService并重写生成的服务,然后在启动程序映射服务接口

//服务端流接口
public override async Task ExcuteServerStream(StreamForClientRequest req,IServerStreamWriter<StreamForClientRespones> resStream,ServerCallContext context)
{
    //list集合作为模拟数据源
    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);
        //模拟源源不断的数据响应
        await Task.Delay(1000);
    }
}

//客户端流接口
public override async Task<StreamForClientRespones> ExcuteClientStream( IAsyncStreamReader<StreamForClientRequest> requestStream, ServerCallContext context)
{
    StreamForClientRespones intArrayModel = new StreamForClientRespones();
    //获取请求流中的数据
    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;
    //从流中获取请求
    while (await reqStream.MoveNext())
    {
        i++;
        var ele = new StreamForClientRespones();
        ele.Number.Add(i);
        //写入响应流
        await resStream.WriteAsync(ele);
        await Task.Delay(500);
    }
}

3.创建客户端调用,把服务端的protobuf文件拷贝到客户端,然后生成,启动调用

//调用服务端流 
using (var channel = GrpcChannel.ForAddress("https://localhost:7245"))
 {
     var client = new StreamTest.StreamTestClient(channel);
     //调用服务端流
     var reply =  client.ExcuteServerStream(new StreamForClientRequest { Id =1});

     //利用线程取消
     //CancellationTokenSource cts = new CancellationTokenSource();
     //指定在2s后进行取消操作
     //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]);
     }
 }

 //调用客户端流
 using (var channel = GrpcChannel.ForAddress("https://localhost:7245"))
 {
     var client = new StreamTest.StreamTestClient(channel);
     //调用客户端流接口
     var reply = client.ExcuteClientStream();

     //模拟源源不断的数据发送
     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("*************发送完毕*******************");
     await reply.RequestStream.CompleteAsync();
     //接受结果
     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);
    //调用双向流接口
    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);
    }
    //发送完毕
    await reply.RequestStream.CompleteAsync();
    //开始接收响应
    await bathCatRespTask;
}

2.NetCore Web项目作为客户端

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

2.在web项目中的控制器中,我们就不能直接简陋的使用 using的方式来连接gRPC服务端了,可以利用内置的依赖注入的模式来完成

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.调用出现如下问题 ,使用dotnet dev-certs https --trust

3.gRPC AOP拦截

有时候我们想在gRPC服务执行前后做一些操作,这时候可以使用其Aop拦截,如果你要问拦截器可以做什么,我不太想解释,继续往下看,拦截器方法定义在Interceptor类中,服务端和客户端拦截是一样的原理,下面列举一些拦截器:

名称特点
BlockingUnaryCall拦截阻塞调用
AsyncUnaryCall拦截异步调用
AsyncServerStreaminGCall拦截异步服务端流调用
AsyncClientStreamingCall拦截异步客户端流调用
AsyncDuplexStreamingCall拦截异步双向流调用
UnaryServerHandler用于拦截和传入普通调用的服务器端处理程序
ClientStreamingSerHandler用于拦截客户端流调用的服务器端处理程序
ServerStreamingSerHandler用于拦截服务端流调用的服务器端处理程序
DuplexStreamingSerHandler用于拦截双向流调用的服务器端处理程序

1.声明一个UnaryServerHandlerInterceptor类型的自定义拦截器,用于拦截和传入普通调用的服务器端处理程序,然后继承自Grpc.Core.Interceptors.Interceptor类, 重写已经定义的方法UnaryServerHandler

public class UnaryServerHandlerInterceptor : Interceptor
{
    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
       TRequest request,
       ServerCallContext context,
       UnaryServerMethod<TRequest, TResponse> continuation)
    {
        Console.WriteLine("执行调用前");
        var result = await continuation(request, context);
        Console.WriteLine("执行调用后");
        // 或向 客户端附加 一些信息
        // 也可以 用try catch 做异常日志
        // 可以从 context中取出 调用方ip,做ip限制
        // 可以 监控continuation 的 执行时间
        return result;
    } 
}

2.然后在注入容器时加入选项

builder.Services.AddGrpc(option => { 
    option.EnableDetailedErrors = true;
    //加入服务端拦截器选项
    option.Interceptors.Add<UnaryServerHandlerInterceptor>();
});

到此这篇关于.NET Core中使用gRPC的文章就介绍到这了,更多相关.NET Core使用gRPC内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: .NET Core中使用gRPC的方法

本文链接: https://www.lsjlt.com/news/167089.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • .NET Core中使用gRPC的方法
    目录1.什么是gRPC1.基本介绍2.proto文件3.上手实践2.gRPC流1.服务端流、客户端流、双向流2.NetCore Web项目作为客户端3.gRPC AOP拦截1.什么是...
    99+
    2022-11-13
  • .NET Core(.NET6)中gRPC使用实践
    目录一、简介二、创建gRPC服务端1.创建gRPC项目2.编写自己的服务三、创建gRPC客户端1.创建客户端项目2.grPC服务https的调用3.gRPC内网http调用4.IOC...
    99+
    2022-11-13
  • .Net Core微服务rpc框架GRPC通信的方法是什么
    本文小编为大家详细介绍“.Net Core微服务rpc框架GRPC通信的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“.Net Core微服务rpc框架GRPC通信的方法是什么”文章能帮助大家解决疑惑,下面跟...
    99+
    2023-06-26
  • .Net Core下使用Dapper的方法
    目录一、前言二、Dapper环境搭建三、Dapper封装定义DapperDBContext类异步分页构建(PageAsync)定义工作单元与事务定义数据仓储数据库连接四、Dapper...
    99+
    2022-11-12
  • .NET Core中对象池Object Pool的使用方法是什么
    这篇文章主要讲解了“.NET Core中对象池Object Pool的使用方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“.NET Core中对象池Ob...
    99+
    2023-06-25
  • .Net Core 之AutoFac的使用
    目录Autofac介绍组件的三种注册方式生命周期AutoFac 在asp .net core中的使用本文不介绍IoC和DI的概念,如果你对Ioc之前没有了解的话,建议先去搜索一下相关...
    99+
    2022-11-12
  • .NET Core中怎么使用Autofac
    今天小编给大家分享一下.NET Core中怎么使用Autofac的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Au...
    99+
    2023-06-29
  • .net core中编辑json配置文件的方法
    引言 最近在具体项目开发应用中,项目采用的json格式配置文件,配置文件的加载采用的IConfiguration接口对象进行的管理,这是.net standard时代,微软所提供的现...
    99+
    2022-11-12
  • .NET Core读取配置文件的方法
    配置文件是每个项目最基础的部分,也是不可或缺的部分,比如:数据库连接、中间件属性等常见的配置。 今天这篇文章主要内容就是,在.Net Core项目中怎样去读取配置文件并使用。 提前准...
    99+
    2022-11-12
  • .net core异常中间件的使用
    目录正文结正文 if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } 这样写入中间件哈,那么在env环境...
    99+
    2022-11-12
  • .net core静态中间件的使用
    目录正文结正文 我们使用静态文件调用: app.UseStaticFiles(); 那么这个默认会将我们根目录下的wwwroot作为静态目录。 这个就比较值得注意的,可能刚开...
    99+
    2022-11-12
  • .net core Api 部署到Linux的方法步骤
    一.环境介绍 1..net开发环境:asp.net core 3.1 2.Linux环境:CentOS Linux release 7.9.2009 (Core) 3.Swagger: Swashbuckle.As...
    99+
    2022-06-03
    .net core Api部署到Linux .net core Api Linux
  • .NET Core单元测试的方法有哪些
    这篇文章主要介绍“.NET Core单元测试的方法有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“.NET Core单元测试的方法有哪些”文章能帮助大家解决问题。应用程序测试...
    99+
    2023-06-30
  • .net core 使用阿里云分布式日志的配置方法
    前言 好久没有出来夸白了,今天教大家简单的使用阿里云分布式日志,来存储日志,没有阿里云账号的,可以免费注册一个 开通阿里云分布式日志(有一定的免费额度,个人测试学习完全没问题的,香...
    99+
    2022-11-12
  • .net core 中 WebApiClientCore的使用示例代码
    WebApiClient 接口注册与选项 1 配置文件中配置HttpApiOptions选项 配置示例 "IUserApi": { "HttpHost": "http://...
    99+
    2022-12-14
    .net core 中 WebApiClientCore使用 .net core  WebApiClientCore
  • .NET Core 中对象池 Object Pool的使用
    目录一、什么是对象池二、.NET Core 中的对象池三、本文小结一、什么是对象池 对象池简单来说就是一种为对象提供可复用能力的软件设计思路。我们常说有借有还,再借不难,而对象池就...
    99+
    2022-11-12
  • .NET Core类库项目中读取appsettings.json配置的方法
    这是一位朋友问我的问题,写篇随笔回答一下。有2种方法,一种叫丑陋的方法 ——IConfiguration ,一种叫优雅的方法 —— I...
    99+
    2022-11-13
  • Android上使用grpc的方法教程
    前言最近的一个项目使用到了grpc实现跨平台的远程调用,在安卓端使用的时候遇到了一些坑,这里记录一下。首先根据grpc android的官方Demo配置grpc依赖,测试它的hello world工程。编译谷歌官方的helloworld工程...
    99+
    2023-05-31
    android grpc 使用
  • 在NET Core 中获取 CPU 使用率
    以下文章来源于微信公众号DotNetCore实战  在 .NET Framework 中,很多人会用 PerformanceCounter 类做这件事情, 如下代码:   ...
    99+
    2022-11-12
  • .Net Core和RabbitMQ限制循环消费的方法
    目录前言循环场景解决方案一次消费消息不重入队列限定重试次数消息头设定次数存储重试次数队列使用Quorum类型队列消息过期参考资料前言 当消费者端接收消息处理业务时,如果出现异常或是拒...
    99+
    2022-11-13
    .net core rabbitmq循环消费 .net core rabbitmq重复消费 .net core rabbitmq消费限制
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作