本地调用,是进程内函数之间的相互调用;
远程调用,是进程间函数的相互调用,是进程间通信 IPC(Inter-Process Communication)的一种方式。通过远程调用,一个进程可以看到其他进程的函数、方法等。
本地过程调用(Local Procedure Call,LPC),是指运行在同一台机器上的进程之间的互相通信,即在多进程操作系统中,运行的不同进程之间可以通过 LPC 进行函数调用。
远程过程调用(Remote Procedure Call,RPC),是指不同机器中运行的进程之间的相互通信,某一机器上运行的进程在不知道底层通信细节的情况下,就像访问本地服务一样,去调用远程机器上的服务。
B/S 架构是基于 HTTP 协议实现的,每次调用接口时,都需要先进行 HTTP 请求。这样既繁琐又浪费时间,不适用于有低时延要求的大规模分布式系统。远程调用的实现大多采用更底层的网络通信协议。
RPC 的原理及应用
RPC 就是调用方采用参数传递的方式,通过调用本机器上的一个函数或方法,去执行远程机器上的函数或方法(可以统称为服务),并返回结果。在整个过程中,RPC 会隐藏具体的通信细节。
电商购物平台例子中的“支付”操作为例:
1.本地服务器也就是机器 A 中的订单系统,调用本地服务器上的支付系统中的支付操作 Pay(Order),该方法会直接调用 Client Stub(其中,Stub 是用于转换 RPC 过程中在订单系统和支付系统所在机器之间传递的参数),这是一次正常的本地调用。2.Client Stub 将方法 Pay、参数 Order 等打包成一个适合网络传输的消息,通过执行一次系统调用(也就是调用操作系统中的函数)来发送消息。
3.订单系统所在机器 A 的本地操作系统通过底层网络通信,将打包好的消息根据支付系统所在机器 B 的地址发送出去。
4.机器 B 上的操作系统接收到消息后,将消息传递给 Server Stub。
5.机器 B 上的 Server Stub 将接收到的消息进行解包,获得里面的参数,然后调用本地的支付订单的操作 Pay(Order)。
6.机器 B 上的支付操作 Pay(Order) 完成后,将结果发送给 Server Stub,其中结果可使用 XDR(External Data Representation,一种可以在不同计算机系统间传输的数据格式)语言表示。
7.机器 B 上的 Server Stub 将结果数据打包成适合网络传输的消息,然后进行一次系统调用发送消息。
8.机器 B 的本地操作系统通过底层网络将打包好的消息发送回机器 A。
9.机器 A 的操作系统接收到来自机器 B 的消息,并将消息发送给本地的 Client Stub。
10.本地的 Client Stub 将消息解包,然后将解包得到的结果返回给本地的订单系统。
到此,整个 RPC 过程结束。
机器 A 上的 Pay(Order)、 Client Stub 和网络调用之间的交互属于本地调用;
机器 B 上的 Pay(Order)、Server Stub 和网络调用之间的交互也属于本地调用;
机器 A 和机器 B 之间的远程调用的核心是,发生在机器 A 上的网络调用和机器 B 上的网络调用。RPC 的目的,其实就是要将第 2 到第 8 步的几个过程封装起来,让用户看不到这些细节。从用户的角度看,订单系统的进程只是做了一次普通的本地调用,然后就得到了结果。
远程调用与本地调用区别:
1.调用 ID 和函数的映射
(1)在本地调用中,进程内可共享内存地址空间,因此程序可直接通过函数名来调用函数。而函数名的本质就是一个函数指针,可以看成函数在内存中的地址。比如,调用函数 f(),编译器会帮我们找到函数 f() 相应的内存地址。
RPC 中,所有的函数必须要有一个调用 ID 来唯一标识。一个机器上运行的进程在做远程过程调用时,必须附上这个调用 ID。
(2)需要在通信的两台机器间,分别维护一个函数与调用 ID 的映射表。两台机器维护的表中,相同的函数对应的调用 ID 必须保持一致。
2.序列化和反序列化
在本地调用中,进程之间共享内存等,因此我们只需要把参数压到栈里,然后进程自己去栈里读取就行。
RPC中,需要调用方把参数先转成一个二进制流,传到被调用方后,被调用方再把二进制流转换成自己能读取的格式。被调用方同样需要该通信层将序列化后的调用结果返回到调用方。
3.网络传输协议
只要调用方和被调用方可以互传数据,就可以作为这个底层通信层。大部分 RPC 框架采用的是 TCP 协议。