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 ...
随机推荐
- POJ 1321 棋盘问题 题解
棋盘问题 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 70224 Accepted: 33254 Description 在一 ...
- AssetBundleMaster_Introduce_EN
This is an integrated solution for building AssetBundles and loading Assets. what it can do is about ...
- python selenium2 动态调试
#coding=utf-8'''Created on 2017-9-9 @author: ceshi 转自https://testerhome.com/topics/9897''' # rpcserv ...
- 【Step-By-Step】第 三 周
本周面试题一览: 什么是XSS攻击,XSS 攻击可以分为哪几类?我们如何防范XSS攻击? 如何隐藏页面中的某个元素? 浏览器事件代理机制的原理是什么? setTimeout 倒计时为什么会出现误差? ...
- Java解决方案
1.新建模板类提示版本太低 Syntax error, type parameters are only available if source level is 1.5 当我的eclipse使用jd ...
- [LeetCode] 743. Network Delay Time 网络延迟时间
There are N network nodes, labelled 1 to N. Given times, a list of travel times as directededges tim ...
- Visual Studio 调试系列4 单步后退来检查旧应用状态(使用使用 IntelliTrace 窗口)
系列目录 [已更新最新开发文章,点击查看详细] IntelliTrace 后退会在每个断点处及调试器步骤事件发生时自动拍摄应用程序的快照. 凭借记录的快照便可以返回到上一个断点或步骤,并查看当 ...
- win10配置jdk1.8环境变量
1,安装好jdk之后,目录如下 2,右键计算机 - 属性 - 高级系统设置 3,环境变量 4,新增系统变量JAVA_HOME,输入内容D:\work\Program Files\Java\jdk1.8 ...
- 转 A 、B两张表,找出ID字段中,存在A表,但是不存在B表的数据
A.B两张表,找出ID字段中,存在A表,但是不存在B表的数据,A表总共13W数据,去重后大约3万条数据,B表有2W条数据,且B表的ID有索引. 方法一 使用not in,容易理解,效率低. selec ...
- Visual Studio 2017 无法启动,进程中却有devenv.exe运行的解决办法
双击Visual Studio 2017,系统没有响应,在任务管理器中却发现devenv.exe 已经在运行. 解决办法:启动services.msc.找到Visual Studio Standard ...