vlambda博客
学习文章列表

微服务 - 服务之间的通信gRPC

(给DotNet加星标,提升.Net技能

转自:向上拼搏的人
cnblogs.com/xiongheng/p/13214637.html

介绍


gRPC是一种与语言无关的高性能远程过程调用 (RPC) 框架,gRPC是Google发布的基于HTTP 2.0传输层协议承载的高性能开源软件框架,提供了支持多种编程语言的、对网络设备进行配置和纳管的方法。


由于是开源框架,通信的双方可以进行二次开发,所以客户端和服务器端之间的通信会更加专注于业务层面的内容,减少了对由gRPC框架实现的底层通信的关注。


gRPC 的主要优点是:


  • 现代高性能轻量级 RPC 框架。


  • 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现。


  • 可用于多种语言的工具,以生成强类型服务器和客户端。


  • 支持客户端、服务器和双向流式处理调用。


  • 使用 Protobuf 二进制序列化减少对网络的使用。


这些优点使 gRPC 适用于:


  • 效率至关重要的轻量级微服务。


  • 需要多种语言用于开发的 Polyglot 系统。


  • 需要处理流式处理请求或响应的点对点实时服务。


以上摘自Microsoft Document


微服务中gRPC的交互过程



  1. 交换机在开启gRPC功能后充当gRPC客户端的角色,采集服务器充当gRPC服务器角色;


  2. 交换机会根据订阅的事件构建对应数据的格式(GPB/JSON),通过Protocol Buffers进行编写proto文件,交换机与服务器建立gRPC通道,通过gRPC协议向服务器发送请求消息;


  3. 服务器收到请求消息后,服务器会通过Protocol Buffers解译proto文件,还原出最先定义好格式的数据结构,进行业务处理;


  4. 数据梳理完后,服务器需要使用Protocol Buffers重编译应答数据,通过gRPC协议向交换机发送应答消息;


交换机收到应答消息后,结束本次的gRPC交互。上图展示的是gRPC交互过程的具体流程,这也是Telemetry触发方式其中之一,称为Dial-out模式。


简单地说,gRPC就是在客户端和服务器端开启gRPC功能后建立连接,将设备上配置的订阅数据推送给服务器端。我们可以看到整个过程是需要用到Protocol Buffers将所需要处理数据的结构化数据在proto文件中进行定义。


微服务中gRPC的使用


1、想要使用grpc首先需要先引入gRPC的包


引入包的方法是:选中服务--->打开管理库程序包管理器--->选中浏览--->输入  Grpc.AspNetCore  --->选中第一个下载即可


注释:两个服务之间需要通信则这两个服务都需要引入gRPC的包


2、添加gRPC文件


在服务端中添加Protos文件夹(存储所有gRPC文件),在文件夹中添加一个  协议缓冲区文件,文件后缀为 .proto


设计 gRPC 的文件语法,有关 gRPC 文件语法的详细信息,参考一些国内的博客,如《Protobuf语言指南——.proto文件语法详解》。


我项目中使用的语法:


syntax = "proto3";
option csharp_namespace = "BS.GrpcServices.WorkTask";
package BS.GrpcServices.WorkTask;
service WorkTaskGrpc{
rpc SubmitWorkTask(SubmitRequest) returns (SubmitResponse);
}
message SubmitRequest{
string Id = 1;
int32 Survey = 2;
string OrderId = 3;
}
message SubmitResponse{
bool Result = 1;
}


代码详解:


  • BS.GrpcServices.WorkTask:生成的程序集,供外部引用,引入方法:using BS.GrpcServices.WorkTask;


  • WorkTaskGrpc:程序集中的类,也是存储服务之间通信的方法集,引入程序集后通过继承当前类,则可以调用类中的方法


  • SubmitWorkTask:类中的方法,也是两个服务之间通信的方法,通信的主要逻辑均存在当前方法中


  • SubmitRequest:Request默认代表传入参数,Submit与方法相匹配


  • SubmitResponse:Response默认代表返回值,Submit与方法相匹配


3、项目文件配置


双击客户端的服务项目,打开项目文件(.csproj后缀的文件),在文件中输入以下代码:


<ItemGroup>
<Protobuf Include="Protos\WorkTask.proto" GrpcServices="Server" />
</ItemGroup>


输入完成之后保存即可;


双击客户端的服务项目,打开项目文件(.csproj后缀的文件),在文件中输入以下代码:


<ItemGroup>
<Protobuf Include="..\BS.WorkTask.API\Protos\WorkTask.proto" GrpcServices="Client" Link="Protos\WorkTask.proto" />
</ItemGroup>


输入完成之后保存即可;


4、Startup.cs文件


客户端打开Startup.cs文件,输入以下代码:


AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); //允许使用不加密的HTTP/2协议
services.AddGrpcClient<WorkTaskGrpc.WorkTaskGrpcClient>(options =>
{
options.Address = new Uri(Configuration.GetValue<string>("ServiceUrls:WorkTaskAPI"));
});


代码注解:上述代码是打通gRPC通信的最后一个关键点,客户端通过以上方法与gRPC展开通信,才能访问到服务端的gRPC程序集(BS.GrpcServices.WorkTask)


特别注意:上述代码的第一行,备注为允许使用不加密的 HTTP/2协议 是一定不能忽略的,少了此行代码通信则无法完成,因为gRPC就是通过当前协议来完成通信的


5、方法的实现


实现方法通过引用gRPC程序集,继承 WorkTaskGrpc.WorkTaskGrpcBase 类,实现方法如下:


using BS.GrpcServices.WorkTask;
using Grpc.Core;
namespace BS.WorkTask.API.Services
{
public class WorkTaskService : WorkTaskGrpc.WorkTaskGrpcBase
{
public override async Task<SubmitResponse> SubmitWorkTask(SubmitRequest request, ServerCallContext context)
{
。。。。。。
if(result.Succeeded)
return new SubmitResponse() { Result = true };
else
return new SubmitResponse() { Result = false };
}
}
}


调用方法通过引用gRPC程序集,创建 WorkTaskGrpc.WorkTaskGrpcClient 对象,通过对象调用类中的方法,调用方法如下:


using BS.GrpcServices.WorkTask;
namespace BS.ApiAggregator.Controllers
{
[Route("api/worktask")]
[ApiController]
public class WorkTaskController: ControllerBase
{
WorkTaskGrpc.WorkTaskGrpcClient _workTaskClient;
public WorkTaskController(WorkTaskGrpc.WorkTaskGrpcClient workTaskClient)
{
_workTaskClient = workTaskClient;
}
[HttpPost("submit")]
public async Task<IActionResult> SubmitAsync(GrpcServices.WorkTask.SubmitRequest request)
{
try
{
var clientResult = await _workTaskClient.SubmitWorkTaskAsync(request);
if (clientResult.Result)
{
。。。。。。
return Ok(OperateResult.Success);
}
}
catch (Exception ex)
{
。。。。。
}
}
}
}


提醒事项:


  1. 中间省略的代码是处理逻辑,与gRPC无关


  2. 调用方法在客户端内编写,实现方法在服务服务端被编写,两个位置不可混淆


  3. 客户端代表的是调用方,服务端代表的是被调用方


总结


gRPC的配置相对来说比较复杂,对于一些服务比较少的微服务来说,不建议使用,可以通过传统的httpclient通信即可,相对于纯文本传输来说,gRPC传输的是二进制数据,使得传输数据体积小、负载低,保持更加紧凑和高效,对于传入的参数较大的情况的话,用gRPC的话则显得不够灵活


- EOF -


推荐阅读   点击标题可跳转


看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能 

好文章,我在看❤️