dotnet core 之 gRPC
dotnet core gRPC
原文在本人公众号中,欢迎关注我,时不时的会分享一些心得
HTTP和RPC是现代微服务架构中很常用的数据传输方式,两者有很多相似之处,但是又有很大的不同。HTTP是一种规范性、通用性、非常标准的传输协议,几乎所有的语言都支持,如果要确保各平台无缝衔接,可以考虑使用HTTP协议,例如现在常规的RestFUL,整个传输过程通常使用Json数据格式。以至于不管是前端还是后端都可以很好的对接。
RPC协议不仅仅是服务间通信协议,甚至是进程间也存在。可以降低诸多微服务之间调用成本,屏蔽了通讯细节,调用远程方法处理数据时像调用本地方法一样丝滑顺畅。但是对前端和浏览器不是特别友好。
GRPC是google制定实现的一种Rpc形式,官网解释是:
gRPC是可以在任何环境中运行的现代开源高性能RPC框架。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证。它也适用于分布式计算的最后一英里,以将设备,移动应用程序和浏览器连接到后端服务。
gRPC主要包括四个特点:
- 简单的服务定义且不局限于语言:gRPC基于ProtoBuf协议构建,该协议提供了强大的系列化工具和语言定义服务。
- 跨语言和平台:可自动为多语言或平台生成客户端和服务端内容。
- 快速启动和扩展性:只需极少代码就可以生成整个通讯环境,可以扩展数百万rpc请求。
- 双向流和集成身份验证:基于HTTP/2的传输机制以及双向流和而完全可集成的插入式身份验证机制。
ProtoBuf协议:
该协议是一种序列化结构化数据的灵活,高效,自动化的机制,比xml更小,更快,更简单。您定义要一次构造数据的方式,然后可以使用生成的特殊源代码轻松地使用各种语言在各种数据流中写入和读取结构化数据。您甚至可以更新数据结构,而不会破坏已针对“旧”格式编译的已部署程序。
协议文件定义方式:
这是一个简单的定义,此文件在.proto文件中定义,与语言无关。每个消息类型都有一个或多个唯一编号的字段。每个字段都有一个名称和一个值类型,其中值类型可以是数字(整数或浮点数),布尔值,字符串等。定义好后可以使用编译器生成对应语言的操作对象。
更多协议内容请参阅:https://developers.google.com/protocol-buffers/docs/overview。
.net Core3.0 中的Grpc
- 使用Visual Stduio 2019 创建一个gRPC服务
请注意:此处创建的是使用ASP.NET Core的Grpc服务。也就是说,有WebHost去托管服务的。
后面,我们使用Host通用主机进行托管。 - 先来看看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);
接下来,我们创建一个简单的示例
- 创建两个个Core控制台项目并添加文件夹Protos和Services,分别新增一个demo.proto文件和DemoService.cs文件
- 引入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" />
- 编辑csproj文件:使得支持同时生成client和server代码(作为demo,server端 应该只作为server。生成client和server的代码的应该单独抽出来)
- 服务端:重写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" });
}
}
- 接下来就是创建启动项(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的更多相关文章
- dotnet core各rpc组件的性能测试
一般rpc通讯组件都具有高性特性,因为大部分rpc都是基于二进制和连接复用的特点,相对于HTTP(2.0以下的版本)来说有着很大的性能优势,非常适合服务间通讯交互.本文针对了dotnet core平台 ...
- dotnet core 项目脚手架这种小事嘛...
dotnet core脚手架批处理.bat @echo 请修改批处理文件名后,如:Example.Core ,注释掉goto end,再执行脚本 pause goto end ::goto end s ...
- Dapr Pub/Sub 集成 RabbitMQ 、Golang、Java、DotNet Core
前置条件: <Dapr运用> <Dapr 运用之 Java gRPC 调用篇> <Dapr 运用之集成 Asp.Net Core Grpc 调用篇> 搭建 Rabb ...
- 温故知新,DotNet Core SDK和.Net CLI十八般武艺
简介 .NET命令行接口 (CLI) 工具是用于开发.生成.运行和发布.NET应用程序的跨平台工具链. https://docs.microsoft.com/zh-cn/dotnet/core/too ...
- dotNet Core开发环境搭建及简要说明
一.安装 .NET Core SDK 在 Windows 上使用 .NET Core 的最佳途径:使用Visual Studio. 免费下载地址: Visual Studio Community 20 ...
- dotnet core 使用 MongoDB 进行高性能Nosql数据库操作
好久没有写过Blog, 每天看着开源的Java社区流口水, 心里满不是滋味. 终于等到了今年六月份 dotnet core 的正式发布, 看着dotnet 社区也一步一步走向繁荣, 一片蒸蒸日上的大好 ...
- dotnet Core Asp.net 项目搭建
Asp.Net Core 介绍 Asp.Net Core 目前最新版本 1.0.0-preview2-003131 Asp.Net Core官网:https://dotnet.github.io/ A ...
- DotNet Core 介绍
前言 asp.net core rtm 6月底即将发布,自己也想着为社区做点共享,刚好最近不太忙,看到社区的小伙伴们都在为dotnet core的推广而贡献力量,项目中刚好在用rc2版本,就多写些文章 ...
- 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 ...
随机推荐
- Shel脚本-初步入门之《04》
Shel脚本-初步入门-04 脚本语言的种类 4.脚本语言的种类 4.1 Shell 脚本语言的种类 Shell 脚本语言是弱类型语言(无须定义变量的类型即可使用),在 Unix/Linux 中主要有 ...
- 09、日志轮转+rsync同步
logrotate - rotates, compresses, and mails system logs 日志轮转 rotate 日志切割 轮转 切割 备份 归档 常见 ...
- true false
#include<stdio.h> int main(void) { /* true 1 false 0 */ printf( == ); printf( > ); printf( ...
- 201871010101-陈来弟《面向对象程序设计(java)》第七周学习总结
201871010101-陈来弟<面向对象程序设计(java)>第七周学习总结 项目 内容 <面向对象程序设计(java)> https://www.cnblogs.com/n ...
- zookeper分布式搭建1
1.zookeper的下载与安装,见:https://www.cnblogs.com/wanerhu/p/11144815.html 2.准备三台centos,进入etc/hosts 3.编辑内容 映 ...
- 微信小程序 - 视图层 | 基础语法
视图层 WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件.事件系统,可以构建出页面的结构. 类似前端HTML 一.数据绑定 普通语法 test.wxml ...
- JDOJ 1770 埃及分数
JDOJ 1770: 埃及分数 https://neooj.com/oldoj/problem.php?id=1770 Description 分子均为1的分数叫做埃及分数,因为古代埃及人在进行分数运 ...
- 【oracle】获取指定表空间的所有表名
select owner||'.'||table_name from dba_tables where tablespace_name='A';
- [RN] React Native : Failed to execute aapt
这是我在开发 React Native 本地 Android Studio 3.1.4 时 构建 release 版本失败,而开发环境正常 之前用 Android Studio 2.* 未出现此问题 ...
- [POI2011]Lightening Conductor(决策单调性)
好久没写过决策单调性了. 这题其实就是 $p_i=\lceil\max\limits_{j}(a_j-a_i+\sqrt{|i-j|})\rceil$. 拆成两边,先只考虑 $j<i$,然后反过 ...