dotnet core gRPC


原文在本人公众号中,欢迎关注我,时不时的会分享一些心得

HTTP和RPC是现代微服务架构中很常用的数据传输方式,两者有很多相似之处,但是又有很大的不同。HTTP是一种规范性、通用性、非常标准的传输协议,几乎所有的语言都支持,如果要确保各平台无缝衔接,可以考虑使用HTTP协议,例如现在常规的RestFUL,整个传输过程通常使用Json数据格式。以至于不管是前端还是后端都可以很好的对接。

RPC协议不仅仅是服务间通信协议,甚至是进程间也存在。可以降低诸多微服务之间调用成本,屏蔽了通讯细节,调用远程方法处理数据时像调用本地方法一样丝滑顺畅。但是对前端和浏览器不是特别友好。

GRPC是google制定实现的一种Rpc形式,官网解释是:

gRPC是可以在任何环境中运行的现代开源高性能RPC框架。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证。它也适用于分布式计算的最后一英里,以将设备,移动应用程序和浏览器连接到后端服务。

gRPC主要包括四个特点

  1. 简单的服务定义且不局限于语言:gRPC基于ProtoBuf协议构建,该协议提供了强大的系列化工具和语言定义服务。
  2. 跨语言和平台:可自动为多语言或平台生成客户端和服务端内容。
  3. 快速启动和扩展性:只需极少代码就可以生成整个通讯环境,可以扩展数百万rpc请求。
  4. 双向流和集成身份验证:基于HTTP/2的传输机制以及双向流和而完全可集成的插入式身份验证机制。

    ProtoBuf协议

    该协议是一种序列化结构化数据的灵活,高效,自动化的机制,比xml更小,更快,更简单。您定义要一次构造数据的方式,然后可以使用生成的特殊源代码轻松地使用各种语言在各种数据流中写入和读取结构化数据。您甚至可以更新数据结构,而不会破坏已针对“旧”格式编译的已部署程序。

    协议文件定义方式:



    这是一个简单的定义,此文件在.proto文件中定义,与语言无关。每个消息类型都有一个或多个唯一编号的字段。每个字段都有一个名称和一个值类型,其中值类型可以是数字(整数或浮点数),布尔值,字符串等。定义好后可以使用编译器生成对应语言的操作对象。

    更多协议内容请参阅:https://developers.google.com/protocol-buffers/docs/overview。

.net Core3.0 中的Grpc

  1. 使用Visual Stduio 2019 创建一个gRPC服务



    请注意:此处创建的是使用ASP.NET Core的Grpc服务。也就是说,有WebHost去托管服务的。



    后面,我们使用Host通用主机进行托管。
  2. 先来看看Startup类



    图中这两行代码是关键,services.AddGrpc();将rpc注入到应用程序服务中,

    endpoints.MapGrpcService();则是在中间件启用监听rpc请求。

    默认情况下此时生成项目后,proto文件只会生成Serve的代码。客户端代码生成需要单独做配置。

    微软文档中是将proto文件拷贝到client中,去生成client代码。此时服务和客户端生成配置就不一样了:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

我本人习惯将生成的server和client放在一起,打包后供client端和server端使用,只需要这样设置:

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

配置好后重新生成项目,grpctool会自动生成服务端,客户端代码。

client调用方式(asp.net core gRPC):

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHello(
new HelloRequest { Name = "World" });
Console.WriteLine(response.Message);

接下来,我们创建一个简单的示例

  1. 创建两个个Core控制台项目并添加文件夹Protos和Services,分别新增一个demo.proto文件和DemoService.cs文件
  2. 引入nuget包:
 <PackageReference Include="Google.Protobuf" Version="3.10.1" />
<PackageReference Include="Grpc" Version="2.24.0" />
<PackageReference Include="Grpc.Tools" Version="2.24.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" />
  1. 编辑csproj文件:使得支持同时生成client和server代码(作为demo,server端 应该只作为server。生成client和server的代码的应该单独抽出来)
  2. 服务端:重写GrpcExampleService.GrpcExampleServiceBase中的rpc方法(也就是.proto文件生成的代码内容中的rpc服务方法)
public class DemoService: GrpcExampleService.GrpcExampleServiceBase
{
public override Task<AskResponse> Ask(AskRequest request, ServerCallContext context)
{
return Task.FromResult(new AskResponse {Content = "Hello from Ask"});
} public override Task<ResponseModel> GetName(RequestModel request, ServerCallContext context)
{
return Task.FromResult(new ResponseModel { Name = "Hello Pluto" });
}
}
  1. 接下来就是创建启动项(HOST)了(GrpcServer):

    这次使用通用主机,不适用asp.net core webhost。
public class GrpcServer:IHostedService
{
private readonly GrpcExampleService.GrpcExampleServiceBase _sampleServiceBase; public GrpcServer(GrpcExampleService.GrpcExampleServiceBase sampleServiceBase)
{
_sampleServiceBase = sampleServiceBase;
} /// <summary>
/// 启动自己定义的rpc服务
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task StartAsync(CancellationToken cancellationToken)
{
return Task.Factory.StartNew(() =>
{
GrpcServiceManager.Start(GrpcExampleService.BindService(_sampleServiceBase));
}, cancellationToken);
} /// <summary>
/// 停止
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.Factory.StartNew(() =>
{
GrpcServiceManager.Stop();
}, cancellationToken);
}
}

GrpcServiceManager中就是真正的启动和停止grpc服务:


public class GrpcServiceManager
{
static Server server;
public static void Start(ServerServiceDefinition bindService)
{
if (bindService == null)
throw new ArgumentNullException("bindService");
var services = new List<ServerServiceDefinition>() { bindService };
Start(services); //todo 添加配置,拦截器等等
}
private static void Start(List<ServerServiceDefinition> services)
{
try
{
server = new Server()
{
Ports = { new ServerPort("0.0.0.0", 8890, ServerCredentials.Insecure) }
}; foreach (var service in services)
{
server.Services.Add(service);
}
server.Start();
//todo consul 注册
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
} public static void Stop()
{
try
{
server?.ShutdownAsync().Wait();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
} }
}

注意:这里应该将proto协议 服务端客户端端进行分离,协议生成的代码打包后 被客户端项目和服务端项目引用,这里只是为了简便客户端直接会引用服务,因为要用到GrpcExampleService.GrpcExampleServiceClient

上边的todo 后再后续增加对应的功能。

这样服务端就创建完了。接下来就是创建客户端进行调用:

控制台客户端:

main中实现调用逻辑

static void Main(string[] args)
{
var channel=new Grpc.Core.Channel("127.0.0.1",8890,ChannelCredentials.Insecure);
var democlient=new GrpcExampleService.GrpcExampleServiceClient(channel);
var res= democlient.Ask(new AskRequest
{
Cate = 0,
Key = "1312"
});
var res2 = democlient.GetName(new RequestModel
{
Key = "1313"
});
Console.WriteLine($"Ask={res}.GetName={res2}");
}

然后就可以了,启动服务端,然后再启动客户端,就可以看到调用结果了。

dotnet core 之 gRPC的更多相关文章

  1. dotnet core各rpc组件的性能测试

    一般rpc通讯组件都具有高性特性,因为大部分rpc都是基于二进制和连接复用的特点,相对于HTTP(2.0以下的版本)来说有着很大的性能优势,非常适合服务间通讯交互.本文针对了dotnet core平台 ...

  2. dotnet core 项目脚手架这种小事嘛...

    dotnet core脚手架批处理.bat @echo 请修改批处理文件名后,如:Example.Core ,注释掉goto end,再执行脚本 pause goto end ::goto end s ...

  3. Dapr Pub/Sub 集成 RabbitMQ 、Golang、Java、DotNet Core

    前置条件: <Dapr运用> <Dapr 运用之 Java gRPC 调用篇> <Dapr 运用之集成 Asp.Net Core Grpc 调用篇> 搭建 Rabb ...

  4. 温故知新,DotNet Core SDK和.Net CLI十八般武艺

    简介 .NET命令行接口 (CLI) 工具是用于开发.生成.运行和发布.NET应用程序的跨平台工具链. https://docs.microsoft.com/zh-cn/dotnet/core/too ...

  5. dotNet Core开发环境搭建及简要说明

    一.安装 .NET Core SDK 在 Windows 上使用 .NET Core 的最佳途径:使用Visual Studio. 免费下载地址: Visual Studio Community 20 ...

  6. dotnet core 使用 MongoDB 进行高性能Nosql数据库操作

    好久没有写过Blog, 每天看着开源的Java社区流口水, 心里满不是滋味. 终于等到了今年六月份 dotnet core 的正式发布, 看着dotnet 社区也一步一步走向繁荣, 一片蒸蒸日上的大好 ...

  7. dotnet Core Asp.net 项目搭建

    Asp.Net Core 介绍 Asp.Net Core 目前最新版本 1.0.0-preview2-003131 Asp.Net Core官网:https://dotnet.github.io/ A ...

  8. DotNet Core 介绍

    前言 asp.net core rtm 6月底即将发布,自己也想着为社区做点共享,刚好最近不太忙,看到社区的小伙伴们都在为dotnet core的推广而贡献力量,项目中刚好在用rc2版本,就多写些文章 ...

  9. dotnet core 出现Can not find runtime target for framework '.NETCoreApp,Version=v1.6' 的解决办法

    如果你在更新dotnet core新的类库后运行程序提示如下的错误: Can not find runtime target for framework '.NETCoreAPP, Version=v ...

随机推荐

  1. [Linux] nginx的try_files指令实现隐藏index.php的重写

    1.nginx的try_files指令 ,核心功能是替代rewrite,并且比rewrite更强大的是可以按顺序查找文件是否存在,如果文件都找不到才会执行最后的重定向解决的问题是,如果一个网站的部署是 ...

  2. CSS的四种基本选择器和四种高级选择器

    做个快乐的搬运工:https://blog.csdn.net/DYD850804/article/details/80997251

  3. v8 编译 时长3小时

  4. MySQL中建立Oracle中SCOTT数据示例

    1.创建 scott 数据库 CREATE DATABASE scott; 2.创建 scott 数据库中的 dept 表 CREATE TABLE dept( deptno INT UNSIGNED ...

  5. 【作用域】词法作用域(静态作用域,如:js)、动态作用域(如:.bash脚本)

    作用域 作用域是指程序源代码中定义变量的区域. 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限. JavaScript 采用词法作用域(lexical scoping),也就是静态作 ...

  6. (day44)css样式、css布局

    目录 一.css样式 (一)文字样式 (1)文字字体font-family (2)字体大小font-size (3)字体粗细font-weight (4)字体颜色color (二)文本样式 (1)文字 ...

  7. 理解Javascript执行过程

    Javascript是一种解释型的动态语言. 在程序中,有编译型语言和解释型语言.那么什么是编译型语言,什么是解释型语言呢? 编译型语言: 它首先将源代码编译成机器语言,再由机器运行机器码(二进制). ...

  8. JS判断是否是ioS或者Android

    每个客户端都带有自身的UA标识,通过JavaScript,可以获取客户端标识,我们可以获取浏览器的userAgent,用正则来判断手机是ios(苹果)还是Android(安卓)客户端. 项目实例:ht ...

  9. AtCoder Grand Contest 035

    Preface Atcoder的题都好劲啊,都是我做不动的计数与构造 就当锻炼自己的思维能力了(基本都是bzt教的) A - XOR Circle bzt说这题数据太水了只要判一下所有数异或值是否为\ ...

  10. [POI2011]Lightening Conductor(决策单调性)

    好久没写过决策单调性了. 这题其实就是 $p_i=\lceil\max\limits_{j}(a_j-a_i+\sqrt{|i-j|})\rceil$. 拆成两边,先只考虑 $j<i$,然后反过 ...