Dubbo源码——集群策略
Dubbo的集群策略一共分8种,分别是:
- FAIL_OVER(Default)
- FAIL_BACK
- FAIL_SAFE
- FAIL_FAST
- BROADCAST
- AVAILABLE
- FORKING
- MERGEABLE
今天来看一下这几种策略的实现。
FAIL_OVER
即失败重试(换一个提供者),我们看一下代码:
1 | // retry loop. |
这里我们考虑一种异步的情况,异步的情况下,更建议使用Listenable Future
的方式实现,这里给出一个demo:
1 | Future invoke(args,tryCount,failoverFuture) { |
这样的实现方式在异步的情况下就非常优雅了。
FAIL_BACK
失败重试,看代码:
1 | try { |
这里注意一下,如果出错就返回一个空的Result,而不是等待重试的结果。看一下这个addFailed
:
1 | if (retryFuture == null) { |
如果这个invoker
没有重试,则初始化一个重试
,注意这里的重试并不会去换一个提供者,而是继续在这个提供者上重试。
看一下retryFailed
方法:
1 | if (failed.size() == 0) { |
可以看到就是循环这个map,执行所有失败了的invoke过程。
这里我们区分一下failover和failback:
- failover可以重试不止一次
- failover在失败时,进行重试,返回的是重试的结果。而failback返回的是一个空result
- failback不会更换一个提供者(invoker)进行重试
FAIL_SAFE、FAIL_FAST和AVAILABLE比较简单就跳过了
BROADCAST
广播,一次执行对所有的提供者都进行一次调用:
1 | checkInvokers(invokers, invocation); |
其实也没有什么好看的,只需要注意一点即可:广播模式中,如果有一次调用失败,则返回失败。
FORKING
这个就比较有意思了,注释给出的解释是:用在一些实时性要求比较高的读操作。
我们看一下这个实现,分两块来看:
1 | checkInvokers(invokers, invocation); |
从上面的代码我们可以看出,首先,并发的去执行invoke,如果成功就把结果扔进队列,如果失败就把异常扔进队列。
继续往下看,下面的是有意思的地方:
1 | try { |
这里直接从队列里poll一个元素出来,超时时间就是我们之前的timeout。如果是异常就抛出异常,如果是正常结果就返回,其他元素不作考虑。
之前我对这个地方有点疑惑,不太明白这样做的目的。在我的印象里应该是这样的:不断的poll队列中的元素(不超时的情况下),如果是异常就丢弃,如果是正常结果就返回。
如果像dubbo一样,可能会忽略很多成功的结果。今天重读的时候,看了一下注释才豁然开朗。dubbo的这种集群策略上写着:用于对实时性要求比较高
的场景。这里我就理解了:优先速度,其次才是结果。对调用方来说,这种场景意味着对相应速度的依赖更高,那么不管最先返回的是成功的结果还是失败的结果,都直接返回给调用方。
MERGEABLE
把多个调用的结果组装成一个返回。这个依赖另外的一个Merger
类,这里就不细说了。有兴趣的大家自己看一下源码吧。或者需求多的话,我再展开写一下。