Protobuf的RPC序列化和调用原理

前面也有一篇文章,当时直接深入到底层的代码了,反而对于这个调用过程不是很熟悉了,所以这里进行讲讲。(有兴趣可以看一下:基于Protobuf的RPC_proto rpc-CSDN博客

对于分布式系统 ,我们需要协调不同系统间的通信机制,因此就有了RPC和Restful api的两个主流的形式。Restful 主要是基于http协议作为一个通信的载体,因此其更多的是面向公共的接口,提供外部服务用的。而RPC则是自己定义的一个方法,然后设计方法参数和返回值的,restful基于http的方法进行访问资源的。

有了restful,为什么要考虑用rpc呢?我们回到使用场景,在分布式内部调用服务的时候,肯定是要保证速度的,所以速度是第一位 的。因此就有了早期的将rpc的消息序列化成二进制的格式进行通过网络进行传输。但是,随着安全性的提升,必须要保证消息的安全性,所以就有了基于http2进行数据传输的grpc,利用了http2的分帧,二进制,头部压缩,流控制的方式进行优化。

前言讲完了,我们这里讲讲最基础的rpc,基于Protobuf的rpc。我们还是直接使用以前的例子,做简单的分析。

复制代码
message ResultCode
{
    int32 errcode = 1; 
    bytes errmsg = 2;
}
message LoginRequest
{
    bytes name = 1;
    bytes pwd = 2;
}
message LoginResponse
{
    ResultCode result = 1;
    bool sucess = 2;
}
message RegisterRequest
{
    uint32 id = 1;
    bytes name = 2;
    bytes pwd = 3;
}
message RegisterResponse
{
    ResultCode result = 1;
    bool sucess = 2;
}
service UserServiceRpc
{
    rpc Login(LoginRequest) returns(LoginResponse);
    rpc Register(RegisterRequest) returns(RegisterResponse);
}

在网络中数据传输,一般有基于像http的/r/n作为一个消息进行传输。而基于二进制的数据怎么传输呢?我们可以通过,message_length(4字节)+message_content(message表示的长度)。message怎么设计呢?因为message内部也有不同的属性,比如ResultCOde:可以设计成一个字节的类型表示int,四个字节表示真实的errcode的真实内容。所以一个ResultCode可以设计成message_length(4字节)+message_content((1字节表示类型+4字节的类型内容)+(1字节类型+1字节类型)....)最后都生成的是二进制的数据。这里类型可能也会进行压缩,比如使用4 bit进行区分等等。

我们这里拓展,讲讲上面的代码,我们看到message是消息的类型。Service则是定义内部分布式调用的服务,rpc Login(LoginRequest) returns(LoginResponse);则是定义了一个方法。所以,这里服务器A提供A服务,服务器B提供B服务。A和B服务可能有很多方法,我们怎么做区分呢?这里就是有一个或者多个的数组,Protobuf里称为描述符的东西,我们直接通过一个Service找到其方法的描述符,同时一个方法的描述符内部也有一个服务的描述符,二者的关系是(一个Service,多个method)。

这里,我们讲一下整体的过程:

1.服务的发起者

复制代码
调用方:Stub
//1MprpeChannel是底层序列化request的地方,以及发送数据的地方
fxbug:UsereveStustuwhnnelO)
//2.rpe方法的请求参数
fixbug:LoginRequest request
request.set_name("zhang san");
requestset_pwd("123456");
//3.rpe方法的响应
fixbug:LoginResponse response,
//4.发起rpc方法的调用同步的rpc调用过程MprpcChannel:callmethod
a
// 4.1 定义rpe的请求header
mprpc:RpcHeader rpcHeader;,
pcHeader.setservicnameservicname);
rpcHeader.setmethodname(methodname);
rpHeadersetarg_size(args_size);
//4.2 序列化rpcheader
uint32 theader size =0;
tstringpheaderst
if(pHeaderSerializeToString(&pheaderst)
{
header_size=pcheader_st.size0:
1
else
{
controller->SetFailed("serializepheadererror!"):
return;
}
4.3序列化所有消息
//组织待发送的rpc请求的字符串
std:string send_rpc_st,
isis
send_xpc_st+=rpc_headet_st://rpcheader
send_xpc_st+=arg_st;//arg
5. 反序列化Response
response->ParseFromArray
  1. 服务的提供者

    1. 服务的发布注册
      RpcProvider::NotifyService(google::protobuf::Service *service)
    2. 请求的解析
      mprpc::RpcHeader rpcHeader;
      std::string service_name;
      std::string method_name;
      uint32_t args_size;
      rpcHeader.ParseFromString(rpc_header_str)
      通过序列化得到的数据,得到对应的方法名,最后找到对应的方法
      3.执行request的回调,返回response
      google::protobuf::Closure done = google::protobuf::NewCallback<RpcProvider,
      const muduo::net::TcpConnectionPtr&,
      google::protobuf::Message
      >(this,&RpcProvider::SendRpcResponse, conn, response);
      调用服务的回调
      service->CallMethod(method, nullptr, request, response, done);
相关推荐
嵌入式×边缘AI:打怪升级日志20 小时前
[特殊字符] USBX 学习笔记(基于 Azure® RTOS)
网络
米羊12121 小时前
Linux 内核漏洞提权
网络·安全·web安全
运维行者_1 天前
2026 技术升级,OpManager 新增 AI 网络拓扑与带宽预测功能
运维·网络·数据库·人工智能·安全·web安全·自动化
Ar呐1 天前
软考网规篇之局域网——网关冗余技术VRRP
网络·计算机网络
头发还没掉光光1 天前
HTTP协议从基础到实战全解析
linux·服务器·网络·c++·网络协议·http
漂洋过海的鱼儿1 天前
设计模式——EIT构型(三)
java·网络·设计模式
数通工程师1 天前
企业级硬件防火墙基础配置实战:从初始化到规则上线全流程
运维·网络·网络协议·tcp/ip·华为
血色橄榄枝1 天前
03 基于Flutter集成网络请求On OpenHarmony
网络·flutter
Godspeed Zhao1 天前
现代智能汽车中的无线技术41——BT与BLE(0)
网络·汽车
那就回到过去1 天前
PIM-DM断言机制和剪枝否决机制
网络·tcp/ip·智能路由器·ensp