一. 简介
gRPC 是一个由 Google 开源的, 跨语言的, 高性能的远程过程调用 (RPC) 框架. gRPC 使客户端和服务端应用程序可以透明地进行通信, 并简化了连接系统的构建. 它使用 HTTP/2 作为通信协议, 使用 Protocol Buffers 作为序列化协议.
它的主要优点:
现代高性能轻量级 RPC 框架.
约定优先的 API 开发, 默认使用 Protocol Buffers 作为描述语言, 允许与语言无关的实现.
可用于多种语言的工具, 以生成强类型的服务器和客户端.
支持客户端, 服务器双向流调用.
通过 Protocol Buffers 二进制序列化减少网络使用.
使用 HTTP/2 进行传输
这些优点使 gRPC 非常适合:
高性能轻量级微服务 - gRPC 设计为低延迟和高吞吐量通信, 非常适合需要高性能的轻量级微服务.
多语言混合开发 - gRPC 工具支持所有流行的开发语言, 使 gRPC 成为多语言开发环境的理想选择.
点对点实时通信 - gRPC 对双向流调用提供出色的支持. gRPC 服务可以实时推送消息而无需轮询.
网络受限环境 - 使用 Protocol Buffers 二进制序列化消息, 该序列化始终小于等效的 JSON 消息, 对网络带宽需求比 JSON 小.
不建议使用 gRPC 的场景:
浏览器可访问的 API - 浏览器不完全支持 gRPC. 虽然 gRPC-web 可以提供浏览器支持, 但是它有局限性, 引入了服务器代理
广播实时通信 - gRPC 支持通过流进行实时通信, 但不存在向已注册连接广播消息的概念
进程间通信 - 进程必须承载 HTTP/2 才能接受传入的 gRPC 调用, 对于 Windows, 进程间通信管道是一种更快速的方法.
摘自微软官方文档
支持的语言如下:
二. gRPC on .NET Core
gRPC 现在可以非常简单的在 .NET Core 和 ASP.NET Core 中使用, 在 .NET Core 上的实现的开源地址: https://github.com/grpc/grpc-dotnet , 它目前由微软官方 ASP.NET 项目的人员进行维护, 良好的接入 .NET Core 生态.
.NET Core 的 gRPC 功能如下:
https://www.nuget.org/packages/Grpc.AspNetCore 一个用于在 ASP.NET Core 承载 gRPC 服务的框架, 将 gRPC 和 ASP.NET Core 功能集成在一起, 如: 日志, 依赖注入, 身份认证和授权.
https://www.nuget.org/packages/Grpc.Net.Client 基于 HttpClient (HttpClient 现已支持 HTTP/2)的 gRPC 客户端
与 gRPC 客户端集成的 HttpClientFactory, 允许对 gRPC 客户端进行集中配置, 并使用 DI 注入到应用程序中
三. 使用 ASP.NET Core 创建 gRPC 服务
通过 Visual Studio 2019 (16.3.0)提供的模板, 可以快速创建 gRPC 服务.
来扒拉一下默认源码包含了什么东东.
1 配置文件 appsettings.JSON , 多了 Kestrel 启用 HTTP/2 的配置, 因为 gRPC 是基于 HTTP/2 来通信的
2 PB 协议文件 greet.proto 用于自动生成服务, 客户端和消息 (表示传递的数据) 的 C# Class
3 服务类 GreeterService , 服务类集成的 Greeter.GreeterBase 来自于根据 proto 文件自动生成的, 生成的类在 obj\Debug\netcoreapp3.0 目录下
自动生成的类:
4 Startup.cs 类, 将 gRPC 服务添加到了终结点路由中
5 csproj 项目文件, 包含了 proto 文件引用
2. 运行
第一次运行会提示是否信任证书, 点击 "是"
这是因为 HTTP/2 需要 HTTPS, 尽管 HTTP/2 协议没有明确规定需要 HTTPS, 但是为了安全在浏览器实现上都要求了 HTTPS, 所以现在的 HTTP/2 和 HTTPS 基本都是一对.
四. 创建 gRPC 客户端
1. 添加一个. NET Core 控制台应用程序
2. 通过 nuget 添加包: Grpc.NET.Client,Google.Protobuf,Grpc.Tools
3. 将服务的 proto 文件复制到客户端
4. 编辑客户端项目文件, 添加关于 proto 文件的描述
- <ItemGroup>
- <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
- </ItemGroup>
注意 GrpcServices="Client" 这里是 Client 和服务是不一样的
5. 生成客户端项目可以通过 proto 文件生成类
6. 添加客户端调用代码
- static async Task Main(string[] args)
- {
- var channel = GrpcChannel.ForAddress("https://localhost:5001");
- var client = new Greeter.GreeterClient(channel);
- var reply = await client.SayHelloAsync(
- new HelloRequest { Name = "晓晨" });
- Console.WriteLine("Greeter 服务返回数据:" + reply.Message);
- Console.ReadKey();
- }
7. 先启动服务, 然后运行客户端
这里可以看到, 客户端成功调用了服务, 收到了返回的消息.
五. 自己动手写一个服务
前面我们使用的 Greeter 服务是由模板自动给我们创建的, 现在我们来自己动手写一个服务.
编写一个 "撸猫服务"
1. 定义 proto 文件 LuCat.proto, 并在 csproj 项目文件中添加描述
- syntax = "proto3";
- option csharp_namespace = "AspNetCoregRpcService";
- import "google/protobuf/empty.proto";
- package LuCat; // 定义包名
- // 定义服务
- service LuCat{
- // 定义吸猫方法
- rpc SuckingCat(google.protobuf.Empty) returns(SuckingCatResult);
- }
- message SuckingCatResult{
- string message=1;
- }
2. 实现服务 LuCatService.cs
- public class LuCatService:LuCat.LuCatBase
- {
- private static readonly List<string> Cats=new List<string>(){"英短银渐层","英短金渐层","美短","蓝猫","狸花猫","橘猫"};
- private static readonly Random Rand=new Random(DateTime.Now.Millisecond);
- public override Task<SuckingCatResult> SuckingCat(Empty request, ServerCallContext context)
- {
- return Task.FromResult(new SuckingCatResult()
- {
- Message = $"您吸了一只{Cats[Rand.Next(0, Cats.Count)]}"
- });
- }
- }
3. 在 Startup 终结点路由中注册
endpoints.MapGrpcService<LuCatService>();
4. 添加客户端调用
- var catClient = new LuCat.LuCatClient(channel);
- var catReply = await catClient.SuckingCatAsync(new Empty());
- Console.WriteLine("调用撸猫服务:"+ catReply.Message);
5. 运行测试
六. 实际使用中的技巧
技巧 1
上面章节的操作步骤中, 我们需要在服务和客户端之间复制 proto, 这是一个可以省略掉的步骤.
1. 复制 Protos 文件夹到解决方案根目录(sln 文件所在目录)
2. 删除客户端和服务项目中的 Protos 文件夹
3. 在客户端项目文件 csproj 中添加关于 proto 文件的描述
- <ItemGroup>
- <Protobuf Include="..\..\Protos\greet.proto" GrpcServices="Client" Link="Protos\greet.proto" />
- </ItemGroup>
4. 在服务项目文件 csproj 中添加关于 proto 文件的描述
- <ItemGroup>
- <Protobuf Include="..\..\Protos\greet.proto" GrpcServices="Server" Link="Protos\greet.proto" />
- </ItemGroup>
在实际项目中, 请自己计算相对路径
5. 这样两个项目都是使用的一个 proto 文件, 只用维护这一个文件即可
技巧 2
我们在实际项目中使用, 肯定有多个 proto 文件, 难道我们每添加一个 proto 文件都要去更新 csproj 文件?
我们可以使用 MSBuild 变量来帮我们完成, 我们将 csproj 项目文件中引入 proto 文件信息进行修改.
服务端:
- <ItemGroup>
- <Protobuf Include="..\..\Protos\*.proto" GrpcServices="Server" Link="Protos\%(RecursiveDir)%(Filename)%(Extension)" />
- </ItemGroup>
客户端:
- <ItemGroup>
- <Protobuf Include="..\..\Protos\*.proto" GrpcServices="Client" Link="Protos\%(RecursiveDir)%(Filename)%(Extension)" />
- </ItemGroup>
示例:
七. 总结
gRPC 现目前是一款非常成熟的高性能 RPC 框架, 当前的生态是非常好的, 很多公司的产品或者开源项目都有在使用 gRPC, 有了它, 相信可以让我们更容易的构建. NET Core 微服务, 可以让 .NET Core 更好的接入 gRPC 生态. 不得不说这是 .NET Core 3.0 带来的最令人振奋的特性之一.
参考资料:
proto3 说明文档
在 ASP.NET Core 中创建 gRPC 客户端和服务
Demo 地址
如果大家无法访问 proto3 说明文档, 这里提供一个离线网页版(请另存为下载后用 Chrome 打开)
来源: https://www.cnblogs.com/stulzq/p/11581967.html