博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dubbo集群容错策略的代码分析3
阅读量:6251 次
发布时间:2019-06-22

本文共 5158 字,大约阅读时间需要 17 分钟。

hot3.png

接上篇

dubbo 版本2.5.3

通过代码可以看到failback,failover,failsafe,forking,failfast都通过了父类的select方法选择服务提供者(invoker)

这个方法里,也包含有dubbo处理集群的机制,包括使用负载均衡的策略。通知可以看到available和broadcast方案目前没用到负载均衡策略,先看先看select方法

/**     * 使用loadbalance选择invoker.
* a)先lb选择,如果在selected列表中 或者 不可用且做检验时,进入下一步(重选),否则直接返回
* b)重选验证规则:selected > available .保证重选出的结果尽量不在select中,并且是可用的 * * @param availablecheck 如果设置true,在选择的时候先选invoker.available == true * @param selected 已选过的invoker.注意:输入保证不重复 */ protected Invoker
select(LoadBalance loadbalance, Invocation invocation, List
> invokers, List
> 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
invoker = doselect(loadbalance, invocation, invokers, selected); if (sticky) { stickyInvoker = invoker; } return invoker; }

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

private Invoker
doselect(LoadBalance loadbalance, Invocation invocation, List
> invokers, List
> 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
invoker = loadbalance.select(invokers, getUrl(), invocation); //如果选择的提供者,已在selected中包含(优先判断) 或者 // 不可用&&availablecheck=true // 则重新选择 if ((selected != null && selected.contains(invoker)) || (!invoker.isAvailable() && getUrl() != null && availablecheck)) { try { //重新选择 Invoker
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
reselect(LoadBalance loadbalance, Invocation invocation, List
> invokers, List
> selected, boolean availablecheck) throws RpcException { //预先分配一个,这个列表是一定会用到的. List
> reselectInvokers = new ArrayList
>(invokers.size() > 1 ? (invokers.size() - 1) : invokers.size()); //先从非select中选 //把不包含在已选列表中的提供者,放入重选列表reselectInvokers,让负载均衡器选择 if (availablecheck) { //选isAvailable 的非select for (Invoker
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
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
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

dubbo负载均衡

转载于:https://my.oschina.net/u/146130/blog/1569554

你可能感兴趣的文章
答《漫话ID》中的疑问:UniqueID和ClientID的来源
查看>>
STL容器--学习笔记
查看>>
使用Word 2010群发邮件
查看>>
【转】Asp.net控件开发学习笔记整理篇 - 服务器控件生命周期
查看>>
Linux下的shell编程(一)BY 四喜三顺
查看>>
hadoop之 心跳时间与冗余快清除
查看>>
执行计划-数据访问方式(全表扫描与4种索引的方式)
查看>>
Shared_ptr循环引用解决(weak_ptr的作用)
查看>>
P1578 奶牛浴场
查看>>
sqlite 数据库错误 The database disk image is malformed database disk image
查看>>
解决MySQL导入中文乱码
查看>>
11、多线程(三) -- 线程池
查看>>
生成APK时,报错处理
查看>>
简单易懂,原码,补码,反码
查看>>
Postman教程
查看>>
阿里巴巴三板斧
查看>>
谁的青春不迷茫
查看>>
java嵌套类(Nested Classes)总结
查看>>
xming + putty 搭建远程图形化ssh访问ubuntu 14.04
查看>>
php 自带过滤和转义函数
查看>>