1、什么是RPC框架
RPC,全称为Remote Procedure Call,即远程过程调用,是一种计算机通信协议。
如:分别部署了应用A和应用B,位于A机器上的A应用要调用位于B机器上的B应用提供的函数或是方法,A应用和B应用不在一个内存空间里,所以不能直接调用,此时就需要通过网络来表达调用的方式和传输调用的数据。
2、RPC协议组成
一个典型RPC的使用场景中,包含了服务发现、负载、容错、网络传输、序列化等组件,其中RPC协议就指明了程序如何进行网络传输和序列化 。
- ip:服务提供者地址;
- 端口:协议指定开放的端口;
- 运行服务:
netty(默认)
mina
RMI 服务
servlet 容器(jetty、Tomcat、Jboss) - 报文编码(编解码):协议报文编码 。
- dubbo序列化方式:
Hessian2Serialization、(默认)
DubboSerialization、
JavaSerialization
JsonSerialization
3 RPC框架的实现原理
3.1 步骤:
3.1.1 建立通信
A机器想要调用B机器,首先得建立起通信连接。主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有相关的数据都在这个连接里面进行传输交换。
3.1.2 服务寻址
A机器上的应用A要调用B机器上的应用B,要提供B机器(主机名或IP地址)以及特定的端口,然后指定调用的方法或者函数的名称以及入参出参等信息,这样才能完成服务的一个调用
3.1.3 网络传输
序列化/反序列化:A发起RPC调用时,调用方法和入参信息都是需要通过底层的网络协议如TCP传输到B机器,由于网络协议是基于二进制的,所有我们传输的参数数据都需要先进行序列化(Serialize)或者编组(marshal)成二进制的形式才能在网络中进行传输。然后通过寻址操作和网络传输将序列化或者编组之后的二进制数据发送给B机器。
3.1.4 服务调用
B机器进行本地调用(通过代理Proxy)之后得到了返回值,此时还需要再把返回值发送回A机器,同样也需要经过序列化操作,然后再经过网络传输将二进制数据发送回A机器,而当A机器接收到这些返回值之后,则再次进行反序列化操作,恢复为内存中的表达方式,最后再交给A机器上的应用进行相关处理。
4 RPC实现基础
- 需要有非常高效的网络通信,比如一般选择Netty作为网络通信框架
- 需要有比较高效的序列化框架,比如谷歌的Protobuf序列化框架
- 可靠的寻址方式(主要是提供服务的发现),比如可以使用Zookeeper来注册服务等等
- 如果是带会话(状态)的RPC调用,还需要有会话和状态保持的功能
5 调用过程
5.1 组件
- 客户端(Client):服务调用方(服务消费者)
- 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端
- 服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理
- 服务端(Server):服务的真正提供者
5.2 调用过程
6 使用技术
6.1 动态代理
生成Client Stub(客户端存根)和Server Stub(服务端存根)的时候需要用到java动态代理技术,可以使用jdk提供的原生的动态代理机制,也可以使用开源的:Cglib代理,Javassist字节码生成技术。
6.2 序列化
网络中,所有的数据都将会被转化为字节进行传送,较高效的开源序列化框架:如Kryo、fastjson和Protobuf等。
序列化:把对象转换为字节序列的过程称为对象的序列化,也就是编码的过程。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化,也就是解码的过程。
6.3 NIO通信
并发性能的考虑,传统的阻塞式 IO 显然不太合适,因此我们需要异步的 IO,即 NIO。可以选择Netty或者mina来解决NIO数据传输的问题。
6.4 服务注册中心
可选:Redis、Zookeeper、Consul 、Etcd。