1、简介
RPC全称是Remote Procedure Call,它是一种进程间通信方式。允许像调用本地服务一样调用远程服务,它的具体实现方式可以不同,例如Spring的HTTP Invoker,Facebook的Thrift
二进制私有协议通信。
RPC概念术语在上世纪80年代由Bruce Jay Nelson提出,在他的论文中对RPC进行了如下总结。
- 简单:RPC概念的语义十分清晰和简单,这样建立分布式计算就更容易。
- 高效:过程调用看起来十分简单且高效。
- 通用:在单机计算中过程往往是不同算法和API,跨进程调用最重要的通用的通信机制。
2、RPC框架原理
RPC框架的目标就是让远程过程(服务)调用更加简单、透明。RPC框架负责屏蔽底层的传输方式(TCP/UDP)、序列化方式(XML/JSON/二进制)和通信细节。框架使用者只需要了解谁在什么位置提供了什么样的远程服务接口即可,开发者不需要关心通信细节和调用过程。
因此一个RPC的设计需要考虑:传输方式、序列化、通信等方面。
RPC框架调用原理如下图:
RPC框架实现的几个核心技术点如下:
- 远程服务提供者需要以某种形式提供服务调用相关的信息,包括但不限于服务接口定义、数据结构、或者中间态的服务定义文件,如Thrift的IDL文件,WS-RPC的WSDL文件定义,甚至也可以实服务端的接口说明文档;服务调用者需要通过一定的途径获取远程服务调用相关信息,例如服务端接口定义Jar包导入,获取服务端IDL文件等。
- 远程代理对象:服务调用者调用的服务实际是远程服务的本地代理,对应Java语言,它的实现就是JDK的动态代理,通过动态代理的拦截机制,将本地调用封装成远程服务调用。
- 通信:RPC框架和具体的协议无关。
- 序列化:远程通信,需要将对象转换成二进制码流进行网络传输,不同的序列化框架,支持的数据类型、数据包大小、异常类型及性能都不同,不同的RPC框架应用场景不同,因此技术选择也会存在很大差异。一些RPC框架,可以支持多种序列化方式,有的甚至支持用户自定义序列化框架(Hadoop Avro)。
- 要解决通讯的问题,主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
- 要解决寻址的问题,也就是说,A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称名称是什么,这样才能完成调用。比如基于Web服务协议栈的RPC,就要提供一个endpoint URI,或者是从UDDI服务上查找。如果是RMI调用的话,还需要一个RMI Registry来注册服务的地址。
- 当A服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制发送给B服务器。
- B服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达方式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。
- 返回值还要发送回服务器A上的应用,也要经过序列化的方式发送,服务器A接到后,再反序列化,恢复为内存中的表达方式,交给A服务器上的应用。
3、主流RPC框架
- 由Facebook开发的RPC框架Apache Thrift
- Hadoop的子项目Avro-RPC
- caucho提供的基于binary-RPC框架Hessian
- Google开源的基于HTTP/2和ProtocolBuf的RPC框架gRPC