同步服务调用是最经常使用的一种服务调用方式,它的工做原理和使用都很是简单,分布式服务框架默认都须要支持这种调用形式。缓存
它的工做原理以下:客户端发起远程服务调用请求,用户线程完成消息序列化以后,将消息投递到通讯框架,而后同步阻塞,等待通讯线程发送请求并接收到应答以后,唤醒同步等待的用户线程,用户线程获取到应答以后返回。服务器
它的工做原理图如图:网络
为了防止服务端长时间不返回应答消息致使客户端用户线程被挂死,用户线程等待的时候须要设置超时时间,这个超时时间与服务端或者客户端配置的超时时间对应。框架
基于 JDK的 Future机制,能够很是方便地实现异步服务调用。 在实际项目中,每每会扩展 JDK的 Future,提供 Future-Listener机制,它支持主动获取和被动异步回调通知两种模式,适用于不一样的业务场景。
在实际项目中,每每会扩展 JDK的 Future,提供 Future-Listener机制,它支持主动获取和被动异步回调通知两种模式,适用于不一样的业务场景。异步
异步服务调用的工做原理如图 :分布式
异步服务调用的工做流程以下:
1)消费者调用服务端发布的接口,接口调用由分布式服务框架包装成动态代理,发起远程服务调用。
2)通讯框架异步发送请求消息,若是没有发生 I/O异常,返回。
3)请求消息发送成功后, I/O线程构造 Future对象,设置到 RPC上下文中。
4)用户线程经过 RPC上下文获取 Future对象。
5)构造 Listener对象,将其添加到 Future中,用于服务端应答异步回调通知。
6)用户线程返回,不阻塞等待应答。
7)服务端返回应答消息,通讯框架负责反序列化等。性能
8)I/O线程将应答设置到 Future对象的操做结果中。
9)Future对象扫描注册的监听器列表,循环调用监听器的operationComplete方法,将结果通知给监听器,监听器获取到结果以后,继续后续业务逻辑的执行,异步服务调用结束。测试
另一种异步服务调用形式,就是不添加 Listener,用户连续发起 N次服务调用,而后依次从 RPC上下文中获取 Future对象,最终再主动 get结果,业务线程阻塞,相比于老的同步服务调用,它的阻塞时间更短,其工做原理如图。
优化
串行到并行的优化原理如图:因为每次服务调用都是同步阻塞,三个服务调用总耗时为T = T1 + T2 + T3spa
采用异步服务调用以后的优化效果,如图:
采用异步服务调用模式,最后调用三个服务异步操做结果 Future的 get方法同步等待应答,它的总执行时间 T = Max(T1, T2, T3),相比于同步服务调用,性能提高效果很是明显。
串行服务调用比较简单,但在一些业务场景中,须要采用并行服务调用来下降 E2E的时延:
并行服务调用的目标主要有两个:
1)下降业务 E2E时延。
2)提高整个系统的吞吐量。咱们以手游购买道具流程为例,对并行服务调用进行说明,如图。
实现并行服务调用的几种技术方案:
关于批量串行服务调用的流程以下:
1)服务框架提供批量服务调用接口供消费者使用,它的定义样例以下:
2)平台的并行服务调用器建立并行 Future,缓存批量服务调用上下文信息。
3)并行服务调用器循环调用普通的 Invoker,经过循环的方式执行单个服务调用,获取到单个服务的 Future以后设置到 Parallel Future中。
4)返回 Parallel Future给消费者。
5)普通 Invoker调用通讯框架的消息发送接口,发起远程服务调用。
6)服务端返回应答,通讯框架对报文作反序列化,转换成业务对象更新 Parallel Future的结果列表。
7)消费者调用 Parallel Future的 get(timeout)方法, 同步阻塞,等待全部结果所有返回。
8) Parallel Future经过对结果集进行判断,看全部服务调用是否都已经完成(包括成功、失败和异常)。
9)全部批量服务调用结果都已经返回, Notify消费者线程,消费者获取到结果列表,完成批量服务调用,流程继续执行。
经过批量服务调用 + Future机制,咱们实现了并行服务调用,并且没有建立新的线程,用户不用担忧依赖线程上下文的功能出异常。
泛化调用一般包含两种模式:泛化引用和泛化实现。泛化引用主要用于客户端没有 API接口及数据模型的场景,参数及返回值中的全部 POJO均用 Map表示,一般用于框架集成,好比实现一个通用的服务测试框架。泛化实现主要用于服务器端没有 API接口及数据模型的场景,参数及返回值中的全部 POJO均用 Map表示,一般用于框架集成,好比实现一个通用的远程服务Mock框架。泛化调用的设计要点以下。
1)分布式服务框架提供泛化接口,供服务提供者实现和消费者引用,它的参考定义以下:
2)消费者若是引用泛化接口,则直接将请求参数转换成 Map,应答消息也自动转换成 Map。 3)服务提供者若是使用泛化实现发布服务,则自动将请求参数转换成 Map,调用GenService的泛化实现类,应答消息自动包装成 Map返回。 泛化调用因为比较灵活,没有服务契约,所以在实际项目中慎用,它一般用于测试集成、系统上线以后的回声测试等。