关于 RPC 的理解

如何理解 RPC

rpc 全称是远程过程调用,和本地过程调用一样,都属于进程间通信。不通的是,本地过程调用是同一物理机器上的进程间通信,而远程过程调用是在不同的物理机器上进行通信的,并且使其像是调用本地子程序一样简单,(注意,这里所说的子程序,可以认为就是函数)。

本地程序如何调用子程序

  1. 找到要执行的函数地址(本质是跳转到子函数的正文区地址);
  2. 传入参数(本质上,是将参数压栈);
  3. 执行子程序代码并返回结果。

因此,远程过程调用的需要解决的问题就是,如何通知远程机器需要执行哪一个函数,如何参数和返回值。

(1)如何确定调用哪一个子程序

本地调用子程序的时候,确定调用哪一个函数,是直接通过函数名即可,即通过函数的地址。而远程机器上的地址又是如何知晓的呢?因此,最初的实现,就是一个call Id 的映射表查询,比如客户端传来需要调用的函数的函数名,通过一个函数映射表,就可以找到实际需要执行的函数的实际地址。

(2)如何传参数

本地执行子程序的时候是:直接将需要的参数传给子程序即可(底层的实现是将参数进行压栈,暂时可以不管,只关心上层的调用),rpc 是调用远程机器上的“子程序”,因此,首先是需要通过网络将参数传递掉服务端的机器上。这一层同过网络既可以办到,暂不考虑如何方便。

(3)远程机器执行并返回结果

远程接收到需要执行的函数和参数信息之后,就可以执行程序并将结果返回给客户端。这就基本是 rpc 的工作过程。

《关于 RPC 的理解》 rpc调用过程.png

如图所示,图片中的描述的 rpc 执行的顺序是、

  1. client 确定调用的函数以及参数信息;
  2. 对 client 确定的信息进行一次封装,并交给socket(网络);
  3. socket 将封装后的信息发送到服务器端;
  4. 服务器对的网络接收数据并将其传递到上层;
  5. 对数据进行解封,并根据传过来的数据确定需要调用的函数;
  6. 执行相应的函数,并将结果交给封装层;
  7. 封装对返回结果进行封装,并交给网络模块;
  8. 网络模块将结果传递给client端的封装层;
  9. client端的封装层对数据进行解封,获取具体数据;
  10. 实际调用 rpc 的地方获取执行结果。

实际上,为了client调用过程中的透明性,client 的封装层对client外层提供基本和本地子程序相同的程序接口。同时,由于参数可能是一个地址或者是其他比较复杂的对象,内部的数据并不是存储在一块连续的空间中,这里会有一个序列化的过程,将存储的不同地方的数据进行调整成方便发送的数据进行发送。相对的server端就会有反序列化的操作。如果考虑到数据的大小以及安全性的问题时,可能封装层就会对数据进行压缩和加密处理。server也就需要对数据进行解密和解压缩处理。
关于传递的数据的形式:可以是key-value对的xml或者时json形式。也可以是使用类似于protobuf的协议进行传输。
而实现调用函数之间的绑定可以使用反射寻找相应的函数,也可以使用std::bind绑定对应的函数。

总结:rpc只是一种技术思想,并不是某一个特定的事物,他的目的就是使调用远程机器上的子程序像调用本地子程序一样简单,至于使用什么样的技术实现这一点,完全没有限制,而实现这个目的的具体内容是,如何确定调用的函数,如何进行信息通信而已。

    原文作者:nanfeng_mxh
    原文地址: https://www.jianshu.com/p/ec61660a315b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞