在使用dubbo时,通常会遇到timeout这个属性,timeout属性的作用是:给某个服务调用设置超时时间,如果服务在设置的时间内未返回结果,则会抛出调用超时异常:TimeoutException,在使用的过程中,我们有时会对provider和consumer两个配置都会设置timeout值,那么服务调用过程中会以哪个为准?橘子同学今天主要针对这个问题进行分析和扩展。
三种设置方式
以provider配置为例:
####
优先级选择
在dubbo中如果provider和consumer都配置了相同的一个属性,比如本文分析的timeout,其实它们是有优先级的,consumer方法配置 > provider方法配置 > consumer接口配置 > provider接口配置 > consumer全局配置 > provider全局配置。所以对于小橘开始的提出的问题就有了结果,会以消费者配置的为准,接下结合源码来进行解析,其实源码很简单,在RegistryDirectory类中将服务列表转换为DubboInvlker方法中进行了处理:
private
重点就是上面mergeUrl方法,将provider和comsumer的url参数进行了整合,在mergeUrl方法有会调用ClusterUtils.mergeUrl方法进行整合,因为这个方法比较简单,就是对一些参数进行了整合了,会用consumer参数进行覆盖,这里就不分析了,如果感兴趣的同学可以去研究一下。
超时处理
在配置设置了超时timeout,那么代码中是如何处理的,这里咱们在进行一下扩展,分析一下dubbo中是如何处理超时的,在调用服务方法,最后都会调用DubboInvoker.doInvoke方法,咱们就从这个方法开始分析:
@Override
在这个方法中,就以同步模式进行分析,看request方法,request()方法会返回一个DefaultFuture类,在去调用DefaultFuture.get()方法,这里其实涉及到一个在异步中实现同步的技巧,咱们这里不做分析,所以重点就在get()方法里:
@Override
在调用get()方法时,会去调用get(timeout)这个方法,在这个方法中会传一个timeout字段,在和timeout就是咱们配置的那个参数,在这个方法中咱们要关注下面一个代码块:
if
重点看await()方法,会进行阻塞timeout时间,如果阻塞时间到了,则会唤醒往下执行,超时跳出while循环中,判断是否有结果返回,如果没有(这个地方要注意:只有有结果返回,或超时才跳出循环中),则抛出超时异常。讲到这里,超时原理基本上其实差不多了,DefaultFuture这个类还有个地方需要注意,在初始化DefaultFuture对象时,会去创建一个超时的延迟任务,延迟时间就是timeout值,在这个延迟任务中也会调用signal()方法唤醒阻塞。
分批调用
不过在调用rpc远程接口,如果对方的接口不能一次承载返回请求结果能力,我们一般做法是分批调用,将调用一次分成调用多次,然后对每次结果进行汇聚,当然也可以做用利用多线程的能力去执行。后面文章小橘将会介绍这种模式,敬请关注哦!
/**