分布式通信:远程调用
分布式的本质是多进程协作,共同完成任务,我们需要关注进程之间如何通信。
什么是本地调用和远程调用?
本地调用指的是进程内函数之间互相调用;远程调用时进程间函数相互调用,是一种进程间的通信模式。
远程调用分为两类:
- 本地过程调用(Local Procedure Call,LPC),同一台机器上运行的不同进程之间的互相通信,即在多进程操作系统中,运行在不同进程之间可以通过LPC进行函数调用。
- 远程过程调用(Remote Procedure Call,RPC),不同机器上运行的进程之间的相互通信,某一机器上运行的进程在不知道底层通信细节的情况下,就像访问本地服务一样,去调用远程机器上的服务。
远程调用一般不会采用HTTP协议去传输数据,而是采用更底层的网络通信协议,例如TCP。
两种常见的远程调用机制:
- 远程过程调用(Remote Procedure Call,RPC)
- 远程方法调用(Remote Method Invocation,RMI)
RPC就是像调用本地机器上的函数或者方法一样,去执行远程机器上的函数或者方法,并返回结果,整个过程中,不会感知到底层具体的通信细节。
RPC和本地调用有什么区别?
第一个区别是调用ID和函数的映射。本地调用是在进程内调用,程序可以直接通过函数名调用函数,而在RPC中,所有的函数必须要有一个调用ID来唯一标识,一个机器上运行的进程在做远程过程调用时,必须附上这个调用ID。
第二个区别是序列化和反序列化。远程调用时,需要在网络上传输数据,而这里的数据只能是二进制数据,这就需要调用方先把参数转成二进制流,在传到服务提供方后,提供方需要将二进制流转换成可识别的对象。调用方将参数转换成二进制流,称为序列化,服务提供方将二进制流转换成可识别的对象,称为反序列化。
第三个区别是网络传输协议,远程调用可以基于不同的网络协议来传输数据,例如TCP,UDP等。
Dubbo的主要架构
Dubbo的架构主要包括4部分:
- 服务提供方,它会向服务注册中心注册自己提供的服务。
- 服务注册中心,负责存储和管理服务提供方注册的服务信息和服务调用方订阅的服务类型等。
- 服务调用方,根据服务注册中心返回的服务所在的地址列表,通过远程调用方式访问远程服务。
- 监控中心,主要统计服务的调用次数和调用时间等信息,以方便进行服务管理合作和服务失败分析。
Dubbo的大致工作流程:
- 服务提供方将自身提供的服务注册到服务注册中心。
- 服务调用方需要向注册中心预订调用服务的提供方地址列表。
- 服务注册中心将服务对应的提供方列表返回给调用方。
- 服务调用方根据服务地址信息进行远程服务调用。
- 服务调用方和服务提供方定时向监控中心发送服务调用次数以及调用时间等信息。
RMI原理和应用
RMI是一个用于实现RPC的Java API,能够让本地Java虚拟机上运行的对象调用远程方法如同调用本地方法,隐藏通信细节。
RMI是RPC的一种具体形式,其原理和RPC基本一致,不同之处在于RMI是基于对象的,充分李永乐面向对象的思想去实现整个过程,其本质就是一种基于对象的RPC实现。
RMI和RPC最大的不同在于调用方式和返回结果的形式,RMI通过对象作为远程接口进行远程方法调用,返回的结果也是对象形式,比如Java对象类型,或者是基本数据类型。
RPC和RMI的详细比较如下图所示。
远程调用也会存在同步调用和异步调用,通常来说:
- 如果调用方需要等待被调用方执行完成并返回结果,这就是同步调用。
- 如果调用方在调用相关方法后,不需要等待执行结果,被调用方执行结束后,可以通过回调通知等方式告知调用方,这就是异步调用。
同步调用适用于需要关注被调用方计算结果的场景;异步调用适用于对响应效率要求高,但是对结果正确性要求相对较低的场景。