3.2 RPC框架

3.2.1 RMI远程方法调用

RMI(Remote Method Invocation)基于Java远程方法协议(Java Remote Method Protocol)和Java的原生序列化,利用java.rmi包实现。它能够使部署在不同主机上的Java对象之间进行透明的通信与方法调用。RMI实现原理如图3-6所示。

图3-6 RMI实现原理

客户端方法调用从客户对象经占位程序(Stub)、远程引用层(Remote Reference Layer)和传输层(Transport Layer)向下,然后再次经传输层,向上穿过远程调用层和骨干网(Skeleton),到达服务器对象。

  • 占位程序:扮演着远程服务器对象的代理角色,使该对象可被客户激活。
  • 远程引用层:处理语义、管理单一或多重对象的通信,决定调用应发往一个服务器还是多个服务器。
  • 传输层:管理实际的连接,并且追踪可以接受方法调用的远程对象。
  • 骨干网:完成对服务器对象实际的方法调用,并获取返回值。返回值向下经远程引用层、传输层,再向上经传输层和远程调用层返回。最后,占位程序获得返回值。

RMI的特性如下:

  • 支持面向对象多态性。
  • 只支持Java语言。
  • 使用Java原生的序列号机制。
  • 底层通信基于BIO(同步阻塞I/O)。

RMI的缺点如下:

  • 支持语言少。
  • 性能较差。

由于RMI使用Java原生的序列号机制与BIO通信机制,导致RMI的性能较差,不建议在性能要求高的场景使用。

3.2.2 Thrift

Thrift是一个跨语言的服务部署框架,采用二进制编码协议,传输协议使用TCP/IP。相对于HTTP协议,TCP/IP协议的性能更高,因为HTTP协议的内容除了应用数据本身外,还带有描述本次请求上下文的数据(比如Header信息、响应码等)。HTTP协议使用文本协议对传输内容进行编码,相对于采用二进制编码协议的TPC/IP协议码流更大。Thrift通过一个中间语言(IDL,接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前支持C++、Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、Smalltalk和OCaml),并由生成的代码负责RPC协议层和传输层的实现。Thrift内部运行原理如图3-7所示。

图3-7 Thrift内部运行原理

Thrift根据接口定义文件,通过代码生成器生成服务器端和客户端代码(支持不同语言),从而实现服务端和客户端跨语言的支持。用户在Thrift描述文件中声明自己的服务,这些服务经过编译后会生成相应语言的代码文件,然后用户实现服务便可以了。Protocol是协议层,定义数据传输格式,可以为二进制或者XML等。Transport是传输层,定义数据传输方式,传输方式可以为TCP/IP传输、内存共享或者文件共享等。

Thrift的特性如下:

  • 支持丰富的语言绑定。
  • Thrift文件生成目标代码,简单易用。
  • 消息定义文件支持注释。
  • 支持多种消息格式,数据结构与传输表现分离。
  • 包含完整的客户端/服务端堆栈,可快速实现RPC。
  • 支持同步和异步通信。

Thrift的缺点如下:

  • 基本没有官方文档,资料缺乏。

3.2.3 Hessian

Hessian是由Caucho提供的基于Binary-RPC协议的轻量级RPC框架。相比WebService,Hessian更简单、快捷。因为采用二进制RPC协议,所以很适合发送二进制数据。Hessian的特性如下:

  • Hessian基于Binary-RPC协议实现。
  • Hessian基于HTTP协议进行传输。
  • Hessian通过其自定义的串行化机制将请求信息进行序列化,产生二进制流。
  • 面向接口编程,请求端通过Hessian本身提供的API来发起请求,响应端根据Hessian提供的API来接收请求。
  • Hessian根据其私有的串行化机制将请求信息进行反序列化,传递给使用者时已是相应的请求信息对象了,处理完毕后直接返回,Hessian将结果对象进行序列化,传输至调用端。
  • 支持多种语言,包括Java、Python、C++、PHT等。
  • 可以与Spring集成,配置比较简单。

3.2.4 Avro-RPC

Apache Avro是一个数据序列化系统。它本身是一个序列化框架,同时实现了RPC的功能。

Avro的特性如下:

  • 丰富的数据结构。
  • 使用快速的压缩二进制数据格式。
  • 提供容器文件用于持久化数据。
  • 提供远程过程调用RPC。
  • 简单的动态语言结合功能,Avro和动态语言结合后,读写数据文件和使用RPC协议都不需要生成代码。

3.2.5 gRPC

gRPC是由Google开发的一款语言中立、平台中立、开源的远程过程调用(RPC)系统。在gRPC中,客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得创建分布式应用和服务更为容易。与许多RPC系统类似,gRPC也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个gRPC服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。

gRPC的特性如下:

  • 基于HTTP/2 :HTTP/2提供了连接多路复用、双向流、服务器推送、请求优先级、首部压缩等机制,可以节省带宽、降低TCP链接次数、节省CPU、帮助移动设备延长电池寿命等。gRPC的协议设计上使用了HTTP2现有的语义,请求和响应的数据使用HTTP Body发送,其他的控制信息则用Header表示。
  • 支持ProtoBuf:gRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、Hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面,压缩和传输效率高,语法简单,表达力强。
  • 多语言支持:gRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前已提供了C版本gRPC、Java版本gRPC-Java和Go版本gRPC-Go,其他语言的版本正在积极开发中,其中gRPC支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,gRPC-Java已经支持Android开发。

3.2.6 其他RPC框架

国内RPC框架如下:

  • Dubbo:国内较早开源的服务治理的Java RPC框架,虽然在阿里巴巴内部竞争中落败于HSF,沉寂了几年,但是在国内得到了广泛的应用,目前Dubbo项目又获得了支持,并且Dubbo 3.0也开始开发。
  • Motan:微博内部使用的RPC框架,底层支持Java,生态圈往Service Mesh发展以支持多语言。
  • RPCX:基于Go的服务治理的RPC框架,客户端支持跨语言。
  • 腾讯Tars:腾讯公司的RPC框架。
  • 百度BRPC:百度公司的RPC框架。

国外RPC框架如下:

  • Thrift:跨语言的RPC框架,由Facebook贡献。
  • Hessian:由Caucho Technology开发的轻量级二进制RPC框架。
  • Avro:来自Hadoop子项目。
  • gRPC:Google出品的跨语言RPC框架,很弱的(实验性的)负载均衡。
  • twirp:twitch.tv开源的一个RESTful风格的RPC框架。
  • go-micro:Go语言的一个服务治理RPC框架。
  • Spring Cloud:新兴产物。