RPC是什么?为什么要使用RPC?开源的RPC框架有哪些?它有什么优势?基于TCP和HTTP协议的RPC调用有什么不同?......带着这些疑问,我们逐个解答🤞。
1. 背景
-
随着企业IT服务的不断发展,单台服务器逐渐无法承受用户日益增长的请求压力时,就需要多台服务器联合起来构成「服务集群」共同对外提供服务。
-
同时业务服务会随着产品需求的增多越来越肿,架构上必须进行服务拆分,一个完整的大型服务会被打散成很多很多独立的小服务,每个小服务会由独立的进程去管理来对外提供服务,这就是「微服务」。
-
当用户的请求到来时,我们需要将用户的请求分散到多个服务去各自处理,然后又需要将这些子服务的结果汇总起来呈现给用户。那么服务之间该使用何种方式进行交互就是需要解决的核心问题。RPC就是为解决服务之间信息交互而发明和存在的。
2. 什么是RPC?
RPC
(Remote Procedure Call)即远程过程调用,是分布式系统常见的一种通信方法。允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。
简单地说,A使用HTTP或者Socket通信协议,通过参数传递远程调用B提供的服务,并得到返回的结果,这么一个调用过程称之为RPC。
3. RPC框架有哪些?
名称 | 描述 |
---|---|
Dubbo | 国内最早开源的RPC框架,由阿里巴巴公司开发并对外开源,仅支持Java语言。 |
Dubbox | 是当当团队基于Dubbox升级的一个版本。是一个分布式的服务架构,可直接用于生产环境作为SOA服务框架。 |
gRPC | 是Google开发的高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于 HTTP/2 协议标准而设计,基于ProtoBuf(Protocol Buffers )序列化协议开发,且支持众多开发语言。本身它不是分布式的,所以要实现上面的框架的功能需要进一步的开发。 |
Thrift | 最初是由Facebook开发的内部系统跨语言的RPC框架,支持多种语言。 |
Motan | 微博内部使用的RPC框架,仅支持Java语言。 |
Tars | 腾讯内部使用的RPC框架,支持C++、Java、Nodejs、Php、Go等语言。 |
SpringCloud | 国外Pivotal公司2014年对外开源的RPC框架,仅支持Java语言。 |
Hprose | 一个MIT开源许可的新型轻量级跨语言跨平台的面向对象的高性能远程动态通讯中间件,它支持众多语言。 |
4. 为什么要使用RPC?
在一个典型RPC的使用场景中,包含了服务发现、负载、容错、网络传输、序列化等组件,而RPC的主要目标是更容易地构建分布式应用。为实现该目标,RPC框架需提供一种透明调用机制,让使用者不必显式的区分本地调用和远程调用。
5. RPC框架组成部分
5.1 服务寻址
服务寻址可以使用Call ID
映射。在本地调用中,函数体是直接通过函数指针来指定的,但是在远程调用中,函数指针是不行的,因为两个进程的地址空间是完全不一样的。所以在RPC中,所有的函数都必须有自己的一个 ID并且唯一。客户端在做远程过程调用时,必须附上这个ID。然后我们还需要在客户端和服务端分别维护一个函数和Call ID的对应表。当客户端需要进行远程调用时,它就查一下这个表,找出相应的Call ID,然后把它传给服务端,服务端也通过查表,来确定客户端需要调用的函数,然后执行相应函数的代码。(映射表一般就是一个哈希表。)
要调用服务,首先你需要一个服务注册中心去查询对方服务都有哪些实例。Dubbo的服务注册中心是可以配置的,官方推荐使用
Zookeeper
。
5.2 序列化和反序列化
客户端怎么把参数值传给远程的函数呢?在本地调用中,我们只需要把参数压到栈里,然后让函数自己去栈里读就行。但是在远程过程调用时,客户端跟服务端是不同的进程,不能通过内存来传递参数。这时候就需要客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式。
只有二进制数据才能在网络中传输,可以使用
Protobuf
或者FlatBuffers
进行序列化和反序列化。
序列化和反序列化的定义是:
- 将对象转换成二进制流的过程叫做序列化。
- 将二进制流转换成对象的过程叫做反序列化。
5.3 网络传输
所有的数据都需要通过网络传输,因此就需要有一个网络传输层。网络传输层需要把Call ID
和序列化后的参数字节流传给服务端,然后再把序列化后的调用结果传回客户端。只要能完成这两者的,都可以作为传输层使用。因此,它所使用的协议其实是不限的,能完成传输就行。
TCP的连接是最常见的,简要分析基于TCP的连接:通常TCP连接可以是按需连接(需要调用的时候就先建立连接,调用结束后就立马断掉),也可以是长连接(客户端和服务器建立起连接之后保持长期持有,不管此时有无数据包的发送,可以配合心跳检测机制定期检测建立的连接是否存活有效),多个远程过程调用共享同一个连接。
6 基于不同协议的RPC调用
6.1 TCP协议
由服务的调用方与服务的提供方建立Socket连接,并由服务的调用方通过Socket将需要调用的接口名称、方法名称和参数序列化后传递给服务的提供方,服务的提供方反序列化后再利用反射调用相关的方法。
最后将结果返回给服务的调用方,整个基于TCP协议的RPC调用大致如此。但是在实例应用中则会进行一系列的封装,如RMI
便是在TCP协议上传递可序列化的Java对象。
6.2 HTTP协议
由服务的调用者向服务的提供者发送请求,这种请求的方式可能是GET
、POST
、PUT
、DELETE
等中的一种,服务的提供者可能会根据不同的请求方式做出不同的处理,或者某个方法只允许某种请求方式。
而调用的具体方法则是根据URL进行方法调用,而方法所需要的参数可能是对服务调用方传输过去的XML
数据或者JSON
数据解析后的结果,最后返回JOSN或者XML的数据结果。
6.3 两种方式的对比
-
基于TCP的协议实现的RPC调用,由于TCP协议处于协议栈的下层,能够更加灵活地对协议字段进行定制,减少网络开销,提高性能,实现更大的吞吐量和并发数。但是需要更多关注底层复杂的细节,实现的代价更高。
-
基于HTTP协议实现的RPC则可以使用
JSON
和XML
格式的请求或响应数据。由于HTTP协议是上层协议,发送包含同等内容的信息,因此使用 HTTP协议传输所占用的字节数会比使用TCP协议传输所占用的字节数更高。
因此在同等网络下,通过HTTP协议传输相同内容,效率会比基于TCP协议的数据效率要低,信息传输所占用的时间也会更长,当然压缩数据,能够缩小这一差距。
通信框架:
MINA
和Netty
。
远程通信协议:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)。
网友评论