RPC( Remote Procedure Call) C++ 基础

本文详细解析了RPC(远程过程调用)的概念模型与实现原理,涵盖了RPC的组件、协议设计、消息编码与传输机制。深入探讨了RPC与HTTP服务的区别,以及主流RPC框架的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、基础 

prc、分布式计算

Nelson

------- 下文摘自 RPC 的概念模型与实现解析 ----------

模型

1. User
2. User-stub
3. RPCRuntime
4. Server-stub
5. Server

组件

  1. RpcServer 
    负责导出(export)远程接口

  2. RpcClient 
    负责导入(import)远程接口的代理实现

  3. RpcProxy 
    远程接口的代理实现

  4. RpcInvoker 
    客户端:负责编码调用信息和发送调用请求到服务端并等待调用结果返回 
    服务端:负责调用服务端接口的具体实现并返回调用结果

  5. RpcProtocol 
    负责协议编/解码

  6. RpcConnector 
    负责维持客户端和服务端的连接通道和发送数据到服务端

  7. RpcAcceptor 
    负责接收客户端请求并返回请求结果

  8. RpcProcessor 
    负责在服务端控制调用过程,包括管理调用线程池、超时时间等

  9. RpcChannel 
    数据传输通道

 

 协议

     协议指 RPC 调用在网络传输中约定的数据封装方式,包括三个部分:编解码消息头 和 消息体

编解码

       客户端代理在发起调用前需要对调用信息进行编码,这就要考虑需要编码些什么信息并以什么格式传输到服务端才能让服务端完成调用。 出于效率考虑,编码的信息越少越好(传输数据少),编码的规则越简单越好(执行效率高)。

我们先看下需要编码些什么信息:

调用编码

  1. 接口方法 

    包括接口名、方法名

  2. 方法参数 

    包括参数类型、参数值

  3. 调用属性 

    包括调用属性信息,例如调用附加的隐式参数、调用超时时间等

 

返回编码

  1. 返回结果 

    接口方法中定义的返回值

  2. 返回码 

    异常返回码

  3. 返回异常信息 

    调用异常信息

 

消息头

       除了以上这些必须的调用信息,我们可能还需要一些元信息以方便程序编解码以及未来可能的扩展。这样我们的编码消息里面就分成了两部分,一部分是元信息、另一部分是调用的必要信息。如果设计一种 RPC 协议消息的话,元信息我们把它放在协议消息头中,而必要信息放在协议消息体中。下面给出一种概念上的 RPC 协议消息头设计格式:

  1. magic 

    协议魔数,为解码设计

  2. header size 

    协议头长度,为扩展设计

  3. version 

    协议版本,为兼容设计

  4. st 

    消息体序列化类型

  5. hb 

    心跳消息标记,为长连接传输层心跳设计

  6. ow 

    单向消息标记,

  7. rp 

    响应消息标记,不置位默认是请求消息

  8. status code 

    响应消息状态码

 

消息体

消息体常采用序列化编码,常见有以下序列化方式:

  1. xml 

    如 webservie SOAP

  2. json 

    如 JSON-RPC

  3. binary 

    如 thrift; hession; kryo 等

 

格式确定后编解码就简单了,由于头长度一定所以我们比较关心的就是消息体的序列化方式。 序列化我们关心三个方面:

  1. __效率__:序列化和反序列化的效率,越快越好。

  2. __长度__:序列化后的字节长度,越小越好。

  3. __兼容__:序列化和反序列化的兼容性,接口参数对象若增加了字段,是否兼容。

  4. 上面这三点有时是鱼与熊掌不可兼得,这里面涉及到具体的序列化库实现细节,就不在本文进一步展开分析了。

传输

      协议编码之后,自然就是需要将编码后的 RPC 请求消息传输到服务端,服务方执行后返回结果消息或确认消息给客户端。RPC 的应用场景实质是一种可靠的请求应答消息流,这点和 HTTP 类似。因此选择长连接方式的 TCP 协议会更高效,与 HTTP 不同的是在协议层面我们定义了每个消息的唯一 id,因此可以更容易的复用连接。

既然使用长连接,那么第一个问题是到底客户端和服务端之间需要多少根连接?实际上单连接和多连接在使用上没有区别,对于数据传输量较小的应用类型,单连接基本足够。单连接和多连接最大的区别在于,每根连接都有自己私有的发送和接收缓冲区,因此大数据量传输时分散在不同的连接缓冲区会得到更好的吞吐效率。

所以,如果你的数据传输量不足以让单连接的缓冲区一直处于饱和状态的话,那么使用多连接并不会产生任何明显的提升,反而会增加连接管理的开销。

连接是由客户端发起建立并维持的,如果客户端和服务端之间是直连的,那么连接一般不会中断(当然物理链路故障除外)。如果客户端和服务端连接经过一些负载中转设备,有可能连接一段时间不活跃时会被这些中间设备中断。为了保持连接有必要定时为每个连接发送心跳数据以维持连接不中断。心跳消息是 RPC 框架库使用的内部消息,在前文协议头结构中也有一个专门的心跳位,就是用来标记心跳消息的,它对业务应用透明。

  1. reserved 

    为字节对齐保留

  2. message id 

    消息 id

  3. body size 

    消息体长 

RPC服务和HTTP服务对比

RPC-01-架构

RPC 的概念模型与实现解析 (这个仔细看)

深入浅出 RPC - 浅出篇

深入浅出 RPC - 深入篇

主流RPC框架:(仅是概念)

Spring的HTTP Invoker(可以参考)

Hadoop的子项目Avro-RPC

caucho提供的基于binary-RPC框架Hessian

Google开源的基于HTTP/2和ProtocolBuf的RPC框架gRPC(可以参考)

待续

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值