RPC是什么?

  

目录
1,什么是RPC ?
2,典型RPC调用框架
3,节俭框架介绍
1,什么是RPC ?
(1) RPC(远程过程调用):远程调用过程。

  
 <代码>服务器一个部署应用,服务器B部署应用B,当一个服务器调用B服务器上的B应用的函数或者方法时,因为不在同一内存空间,不能直接调用,必须通过网络来表达调用的语义传达调用的数据。 
  

既然是调用B机器上的服务,那一个机器自己也创建一个这个服务不就也可以调用了么。原理上是可以这么做,但是随着计算机的横向发展,集群的出现,使得多台机器部署成一个集群来对外提供服务。无法在一个进程内甚至同一台计算机上完成的需求就得需要RPC来实现了。

  

RPC的框架很多,比如最早的额CORBA, Java RMI, Web服务的RPC风格,黑森,节俭,甚至是Rest API。

  

(2)本地过程调用过程

  
 <代码> RPC就是要像调用本地的函数一样去调远程函数。在研究RPC前,我们先看看本地调用是怎么调的。假设我们要调用函数相乘来计算左值*右值的结果: 
  

1整数相乘(int, int r) {

  

2 int y=l * r;

  

3返回y;

  4}

  5

  

6 int左值=https://www.yisu.com/zixun/10;

  

7 int右值=https://www.yisu.com/zixun/20;

  

8 int l_times_r=相乘(左值,右值);

  
 <代码>那么在第8行时,我们实际上执行了以下操作: 
  

将左值和右值的值压栈

  

进入用函数,取出栈中的值10年和20年,将其赋予l和r

  

执行第2行代码,计算l * r,并将结果存在y

  

将y的值压栈,然后从乘返回

  

第8行,从栈中取出返回200年值,并赋值给l_times_r

  
 <代码>以上5步就是执行本地调用的过程。 
  

(3)远程过程调用带来的新问题

  
 <代码>在远程调用时,我们需要执行的函数体是在远程的机器上的,也就是说,将是在另一个进程中执行的。这就带来了几个新问题: 
  

调用ID映射。我们怎么告诉远程机器我们要调用乘法,而不是添加或者FooBar呢?在本地调用中,函数体是直接通过函数指针来指定的,我们调用乘法,编译器就自动帮我们调用它相应的函数指针。但是在远程调用中,函数指针是不行的,因为两个进程的地址空间是完全不一样的,所以,在RPC中,所有的函数都必须有自己的一个ID。这个ID在所有进程中都是唯一确定的。客户端在做远程过程调用时,必须附上这个ID。然后我们还需要在客户端和服务端分别维护一个{函数& lt;——比;叫ID}的对应表。两者的表不一定需要完全相同,但相同的函数对应的叫ID必须相同。当客户端需要进行远程调用时,它就查一下这个表,找出相应的ID,然后把它传给服务端,服务端也通过查表,来确定客户端需要调用的函数,然后执行相应函数的代码。

  

序列化和反序列化。客户端怎么把参数值传给远程的函数呢?在本地调用中,我们只需要把参数压到栈里,然后让函数自己去栈里读就行。但是在远程过程调用时,客户端跟服务端是不同的进程,不能通过内存来传递参数。甚至有时候客户端和服务端使用的都不是同一种语言(比如服务端用c++,客户端用Java或者Python)。这时候就需要客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式。这个过程叫序列化和反序列化。同理,从服务端返回的值也需要序列化反序列化的过程。

  

网络传输。远程调用往往用在网络上,客户端和服务端是通过网络连接的。所有的数据都需要通过网络传输,因此就需要有一个网络传输层。网络传输层需要把调用的ID和序列化后的参数字节流传给服务端,然后再把序列化后的调用结果传回客户端。只要能完成这两者的,都可以作为传输层使用,因此,它所使用的协议其实是不限的,能完成传输就行。尽管大部分RPC框架都使用TCP协议,但其实UDP也可以,而gRPC干脆就用了HTTP2.Java的网状的也属于这层的东西。

  
 <代码>所以,要实现一个RPC框架,其实只需要把以上三点实现了就基本完成了。
  
  叫ID映射可以直接使用函数字符串,也可以使用整数ID。映射表一般就是一个哈希表。
  
  序列化反序列化可以自己写,也可以使用Protobuf或者FlatBuffers之类的。
  
  网络传输库可以自己写套接字,或者用asio, ZeroMQ,网状的之类。 
  

2,典型RPC调用框架

  

RPC的实现和调用框架很多,简单介绍其中几种比较典型的:

RPC是什么?