⾯试准备——rpc⾯试题
1 什么是 RPC ?
RPC (Remote Procedure Call)即远程过程调⽤,是分布式系统常见的⼀种通信⽅法。它允许程序调⽤另⼀个地址空间(通常是共享⽹络的另⼀台机器上)的过程或函数,⽽不⽤程序员显式编码这个远程调⽤的细节。
除 RPC 之外,常见的多系统数据交互⽅案还有分布式消息队列、HTTP 请求调⽤、数据库和分布式缓存等。
其中 RPC 和 HTTP 调⽤是没有经过中间件的,它们是端到端系统的直接数据交互。
简单的说
RPC就是从⼀台机器(客户端)上通过参数传递的⽅式调⽤另⼀台机器(服务器)上的⼀个函数或⽅法(可以统称为服务)并得到返回的结果。
RPC会隐藏底层的通讯细节(不需要直接处理Socket通讯或Http通讯)。
客户端发起请求,服务器返回响应(类似于Http的⼯作⽅式)RPC在使⽤形式上像调⽤本地函数(或⽅法)⼀样去调⽤远程的函数(或⽅法)。
2 为什么我们要⽤RPC?
RPC 的主要⽬标是让构建分布式应⽤更容易,在提供强⼤的远程调⽤能⼒时不损失本地调⽤的语义简洁性。为实现该⽬标,RPC 框架需提供⼀种透明调⽤机制让使⽤者不必显式的区分本地调⽤和远程调⽤。
3 RPC需要解决的三个问题java dubbo
RPC要达到的⽬标:远程调⽤时,要能够像本地调⽤⼀样⽅便,让调⽤者感知不到远程调⽤的逻辑。
Call ID映射。我们怎么告诉远程机器我们要调⽤哪个函数呢?在本地调⽤中,函数体是直接通过函数指针来指定的,我们调⽤具体函数,编译器就⾃动帮我们调⽤它相应的函数指针。但是在远程调⽤中,是⽆法调⽤函数指针的,因为两个进程的地址空间是完全不⼀样。
所以,在RPC中,所有的函数都必须有⾃⼰的⼀个ID。这个ID在所有进程中都是唯⼀确定的。客户端在做远程过程调⽤时,必须附上这个ID。然后我们还需要在客户端和服务端分别维护⼀个 {函数 <--> Call ID} 的对应表。两者的表不⼀定需要完全相同,但相同的函数对应的Call ID必须相同。当客户端需要进⾏远程调⽤时,它就查⼀下这个表,出相应的Call ID,然后把它传给服务端,服务端也通过查表,来
确定客户端需要调⽤的函数,然后执⾏相应函数的代码。
序列化和反序列化。客户端怎么把参数值传给远程的函数呢?在本地调⽤中,我们只需要把参数压到栈⾥,然后让函数⾃⼰去栈⾥读就⾏。但是在远程过程调⽤时,客户端跟服务端是不同的进程,不能通过内存来传递参数。甚⾄有时候客户端和服务端使⽤的都不是同⼀种语⾔(⽐如服务端⽤C++,客户端⽤Java或者Python)。这时候就需要客户端把参数先转成⼀个字节流,传给服务端后,再把字节流转成⾃⼰能读取的格式。这个过程叫序列化和反序列化。同理,从服务端返回的值也需要序列化反序列化的过程。
⽹络传输。远程调⽤往往是基于⽹络的,客户端和服务端是通过⽹络连接的。所有的数据都需要通过⽹络传输,因此就需要有⼀个⽹络传输层。⽹络传输层需要把Call ID和序列化后的参数字节流传给服务端,然后再把序列化后的调⽤结果传回客户端。只要能完成这两者的,都可以作为传输层使⽤。因此,它所使⽤的协议其实是不限的,能完成传输就⾏。尽管⼤部分RPC框架都使⽤TCP协议,但其实UDP也可以,⽽gRPC⼲脆就⽤了HTTP2。Java的Netty也属于这层的东西。
4 实现⾼可⽤RPC框架需要考虑到的问题
既然系统采⽤分布式架构,那⼀个服务势必会有多个实例,要解决如何获取实例的问题。所以需要⼀个服务注册中⼼,⽐如在Dubbo中,就可以使⽤Zookeeper作为注册中⼼,在调⽤时,从Zookeeper获取
服务的实例列表,再从中选择⼀个进⾏调⽤;
如何选择实例呢?就要考虑负载均衡,例如dubbo提供了4种负载均衡策略;
如果每次都去注册中⼼查询列表,效率很低,那么就要加缓存;
客户端总不能每次调⽤完都等着服务端返回数据,所以就要⽀持异步调⽤;
服务端的接⼝修改了,⽼的接⼝还有⼈在⽤,这就需要版本控制;
服务端总不能每次接到请求都马上启动⼀个线程去处理,于是就需要线程池;
5 理论结构模型
RPC 服务端通过RpcServer去导出(export)远程接⼝⽅法,⽽客户端通过RpcClient去导⼊(import)远程接⼝⽅法。客户端像调⽤本地⽅法⼀样去调⽤远程接⼝⽅法,RPC 框架提供接⼝的代理实现,实际的调⽤将委托给代理RpcProxy。代理封装调⽤信息并将调⽤转交给RpcInvoker去实际执⾏。在客户端的RpcInvoker通过连接器RpcConnector去维持与服务端的通道RpcChannel,并使⽤RpcProtocol执⾏协议编码(encode)并将编码后的请求消息通过通道发送给服务端。
RPC 服务端接收器RpcAcceptor接收客户端的调⽤请求,同样使⽤RpcProtocol执⾏协议解码(decode)。
解码后的调⽤信息传递给RpcProcessor去控制处理调⽤过程,最后再委托调⽤给RpcInvoker去实际执⾏并返回调⽤结果。
主流的RPC框架
服务治理型
dubbo:是阿⾥巴巴公司开源的⼀个Java⾼性能优秀的服务框架,使得应⽤可通过⾼性能的 RPC 实现服务的输出和输⼊功能,可以和Spring框架⽆缝集成。dubbo 已经与12年年底停⽌维护升级。
dubbox:是当当团队基于dubbo升级的⼀个版本。是⼀个分布式的服务架构,可直接⽤于⽣产环境作为SOA服务框架。dubbox资源链接motan:是新浪微博开源的⼀个Java框架。它诞⽣的⽐较晚,起于2013年,2016年5⽉开源。Motan 在微博平台中已经⼴泛应⽤,每天为数百个服务完成近千亿次的调⽤。motan资源链接