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);
相关推荐
啊阿狸不会拉杆4 小时前
《计算机网络-自顶向下方法》5.4 ISP之间的路由选择:BGP 读书笔记
网络·计算机网络·接口隔离原则
Delite8025 小时前
摆脱实验室束缚:便携式卡尔费休微量水分检测技术与现场应用解析
大数据·网络·人工智能
ACP广源盛139246256736 小时前
M6/M5 Pro Mac mini 端侧 AI 落地@ACP#YLB3116 中端多盘存储扩展在 AI 服务中的机会与应用场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos
明月_清风6 小时前
MCP vs ACP vs LSP:AI 时代三大协议的「三足鼎立」
人工智能·网络协议·agent
ACP广源盛139246256736 小时前
M6/M5 Pro Mac mini 端侧 AI 新形态@ACP#GSV5800 Serdes 长距离视频传输在 AI 服务中的机会与落地场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos·音视频
我爱cope7 小时前
【计算机网络 | 传输层3:TCP 协议概述:面向连接、可靠传输到底意味着什么?】
网络·网络协议·学习·tcp/ip·计算机网络·传输层
OIDCAT8 小时前
国产USB转千兆网卡芯片CH398-RTL8153国产替代实测与选型
网络·嵌入式硬件·智能硬件·国产芯片·usb转千兆网卡
M--Y10 小时前
Docker数据持久化与网络架构
网络·docker·架构
myy-learn11 小时前
30-HTTP协议
网络·网络协议·http