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. XGBoost 完整推导过程

    参考: 陈天奇-"XGBoost: A Scalable Tree Boosting System" Paper地址: <https://arxiv.org/abs/1603 ...

  2. Hello,DTOS!(下)

    如何验证编写的主引导程序?解决方案设计:将汇编源码编译为二进制机器码(nasm)创建虚拟盘(bximage)将二进制代码写入虚拟盘起始位置(dd)在虚拟机中将虚拟盘作为启动盘执行(vmware) 就算 ...

  3. c# 第三节 vs的安装

    本节内容: 学会安装vs 一:下载 地址:http://down.lansedongli.com/view/30323.html 二.vs2015支持的操作系统 三.vs2015的硬件要求 四.安装 ...

  4. day12_7.12递归函数与算法

    一.递归函数 递归函数是在函数的调用阶段直接或间接的调用自己. 于是下面就是一个简单的递归函数: def func(): print('我调我自己') func() func() 然而结果会报错,因为 ...

  5. day5_7.3 数据类型的各种函数操作

    昨日补充: 1.在代码的编写中,总会有一些分支编写不出来,为了不影响整个系统的跑动,可以使用pass关键字进行跳过.如 count=0 while count<10: if count<5 ...

  6. 16-numpy笔记-莫烦pandas-4

    代码 import pandas as pd import numpy as np dates = pd.date_range('20130101', periods=6) df=pd.DataFra ...

  7. golang和python互相调用

    http://blog.yuanzhaoyi.cn/2018/06/27/golang_python.html python3-ctypes: https://docs.python.org/3.5/ ...

  8. Spring Cloud微服务安全实战_3-6_API安全机制之审计

    审计日志 定义:谁,在什么时间,干了什么事. 位置:认证之后,授权之前. 这样就知道是谁在访问,拒绝掉的访问也能被记录.如果放在认证之前,那么就不知道是谁在访问:如果放在授权之后,就没办法记录被拒绝的 ...

  9. Linux学习笔记-第7天 - 编程还是要多写多练

    编程思路很重要,多写是要熟悉命令用法,多练不只是要熟悉语句常用在什么环境,更要在其基础上,尝试更多的写法.

  10. 洛谷 P3742 umi的函数

    传送门 思路 \(loceaner\)已经蔡虚鲲到连红题都不会做了 因为有\(special\ judge\)所以我们就可以瞎搞了! 由题目可知,只要有一个\(y[i] > x[i]\)则一定没 ...