dubbo集群容错策略的代码分析3


声明:本文转载自https://my.oschina.net/u/146130/blog/1569554,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

接上篇https://my.oschina.net/u/146130/blog/1563305

dubbo 版本2.5.3

通过代码可以看到failback,failover,failsafe,forking,failfast都通过了父类的select方法选择服务提供者(invoker)
这个方法里,也包含有dubbo处理集群的机制,包括使用负载均衡的策略。通知可以看到available和broadcast方案目前没用到负载均衡策略,先看先看select方法

/**      * 使用loadbalance选择invoker.</br>      * a)先lb选择,如果在selected列表中 或者 不可用且做检验时,进入下一步(重选),否则直接返回</br>      * b)重选验证规则:selected > available .保证重选出的结果尽量不在select中,并且是可用的      *      * @param availablecheck 如果设置true,在选择的时候先选invoker.available == true      * @param selected       已选过的invoker.注意:输入保证不重复      */     protected Invoker<T> select(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {         if (invokers == null || invokers.size() == 0)             return null;         String methodName = invocation == null ? "" : invocation.getMethodName();          //是否启用sticky 粘性连接,让客户端总是连接同一提供者         boolean sticky = invokers.get(0).getUrl().getMethodParameter(methodName, Constants.CLUSTER_STICKY_KEY, Constants.DEFAULT_CLUSTER_STICKY);         {             //ignore overloaded method             //可选提供者列表已不包含,上次的stickyInvoker,设置为null              if (stickyInvoker != null && !invokers.contains(stickyInvoker)) {                 stickyInvoker = null;             }             //ignore cucurrent problem             //stickyInvoker不为null,并且没在已选列表中,返回上次的服务提供者stickyInvoker,但之前强制校验可达性。 	    //由于stickyInvoker不能包含在selected列表中,通过代码看,可以得知forking和failover集群策略,用不了sticky属性             if (sticky && stickyInvoker != null && (selected == null || !selected.contains(stickyInvoker))) {                 if (availablecheck && stickyInvoker.isAvailable()) {                     return stickyInvoker;                 }             }         }         //利用负载均衡选一个提供者         Invoker<T> invoker = doselect(loadbalance, invocation, invokers, selected);          if (sticky) {             stickyInvoker = invoker;         }         return invoker;     }

这个方法实现里,包含了dubbo的sticky特性的实现,看下doselect方法

private Invoker<T> doselect(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {         if (invokers == null || invokers.size() == 0)             return null;         //只有一个,不用选了,直接返回         if (invokers.size() == 1)             return invokers.get(0);         //如果只有两个invoker,退化成轮循         if (invokers.size() == 2 && selected != null && selected.size() > 0) {             return selected.get(0) == invokers.get(0) ? invokers.get(1) : invokers.get(0);         }         //大于两个,利用负载均衡选择一个         Invoker<T> invoker = loadbalance.select(invokers, getUrl(), invocation);          //如果选择的提供者,已在selected中包含(优先判断) 或者         // 不可用&&availablecheck=true         // 则重新选择         if ((selected != null && selected.contains(invoker))                 || (!invoker.isAvailable() && getUrl() != null && availablecheck)) {             try {                 //重新选择                 Invoker<T> rinvoker = reselect(loadbalance, invocation, invokers, selected, availablecheck);                 if (rinvoker != null) {                     invoker = rinvoker;                 } else {                     //如果重新选择失败,看下第一次选的位置,如果不是最后,选+1位置.                     int index = invokers.indexOf(invoker);                     try {                         //最后再避免碰撞                         invoker = index < invokers.size() - 1 ? invokers.get(index + 1) : invoker;                     } catch (Exception e) {                         logger.warn(e.getMessage() + " may because invokers list dynamic change, ignore.", e);                     }                 }             } catch (Throwable t) {                 logger.error("clustor relselect fail reason is :" + t.getMessage() + " if can not slove ,you can set cluster.availablecheck=false in url", t);             }         }         return invoker;     }

这个方法里,处理了只有一个或者两个提供者的特殊情况和invoker的重新选择。在看,重选方法:

 /**      * 重选,先从非selected的列表中选择,没有在从selected列表中选择.      *      * @param loadbalance      * @param invocation      * @param invokers      * @param selected      * @return      * @throws RpcException      */     private Invoker<T> reselect(LoadBalance loadbalance, Invocation invocation,                                 List<Invoker<T>> invokers, List<Invoker<T>> selected, boolean availablecheck)             throws RpcException {          //预先分配一个,这个列表是一定会用到的.         List<Invoker<T>> reselectInvokers = new ArrayList<Invoker<T>>(invokers.size() > 1 ? (invokers.size() - 1) : invokers.size());          //先从非select中选         //把不包含在已选列表中的提供者,放入重选列表reselectInvokers,让负载均衡器选择         if (availablecheck) { //选isAvailable 的非select             for (Invoker<T> invoker : invokers) {                 if (invoker.isAvailable()) {                     if (selected == null || !selected.contains(invoker)) {                         reselectInvokers.add(invoker);                     }                 }             }             if (reselectInvokers.size() > 0) {                 return loadbalance.select(reselectInvokers, getUrl(), invocation);             }         } else { //选全部非select             for (Invoker<T> invoker : invokers) {                 if (selected == null || !selected.contains(invoker)) {                     reselectInvokers.add(invoker);                 }             }             if (reselectInvokers.size() > 0) {                 return loadbalance.select(reselectInvokers, getUrl(), invocation);             }         }         //以上都没选择好,最后从select中选可用的.          {             if (selected != null) {                 for (Invoker<T> invoker : selected) {                     if ((invoker.isAvailable()) //优先选available                             && !reselectInvokers.contains(invoker)) {                         reselectInvokers.add(invoker);                     }                 }             }             if (reselectInvokers.size() > 0) {                 return loadbalance.select(reselectInvokers, getUrl(), invocation);             }         }         return null;     }

这个方法,就是实现尽量不从已选列表中选择invoker

本文发表于2017年11月08日 16:33
(c)注:本文转载自https://my.oschina.net/u/146130/blog/1569554,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2376 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1