文档章节

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

w
 wannshan
发布于 2017/11/08 14:31
字数 962
阅读 2023
收藏 13
点赞 2
评论 2

接上篇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

dubbo负载均衡https://my.oschina.net/u/146130/blog/1572870

© 著作权归作者所有

共有 人打赏支持
w
粉丝 17
博文 42
码字总数 79122
作品 0
浦东
技术主管
加载中

评论(2)

1
18856627751
66666
1
18856627751
Chiba
dubbo集群容错机制代码分析1

dubbo版本2.5.3 我们这里以zookeeper作为注册中心为例说明。 这里说的集群,可以理解为,一个接口服务对应有多个提供者。 在dubbo的调用方(reference)看来,每个提供方(service)对应一个...

wannshan
2017/10/23
0
0
基于Dubbo框架构建分布式服务 (二)

Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简...

如何让他和
2016/10/04
625
2
dubbo集群容错策略的代码分析2

接上篇https://my.oschina.net/u/146130/blog/1554766 dubbo版本2.5.3 dubbo本身集群容错策略有7种。都实现了Cluster接口(spi扩展点) 从类结构上看,Cluster接口有9个实现类(其中MockClu...

wannshan
2017/11/06
0
0
基于Dubbo框架构建分布式服务 (二)

Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简...

如何让他和
2016/10/04
207
1
基于Dubbo框架构建分布式服务 (二) 【转】

Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简...

梵蒂冈考虑过
2016/10/04
292
1
Dubbo 实现原理与源码解析系列 —— 精品合集

摘要: 原创出处 http://www.iocoder.cn/Dubbo/good-collection/ 「芋道源码」欢迎转载,保留摘要,谢谢! 1.【芋艿】精尽 Dubbo 原理与源码专栏 2.【老徐】RPC 专栏 3.【肥朝】Dubbo 源码解析...

芋道源码掘金Java群217878901
06/23
0
0
dubbo工作原理,集群容错,负载均衡

dubbo主要核心部件 Remoting:网络通信框架,实现了sync-over-async和request-response消息机制。 RPC:一个远程过程调用的抽象,支持负载均衡、容灾和集群功能。 Registry:服务目录框架用于...

monroeCode
2017/10/23
0
0
百度、阿里、腾讯、京东、大型互联网分布式架构必备技能

分布式架构 迎接高并发大数据的挑战,从深度到广度完善知识体系,成为下一个互联网高薪人才。 理论结合实战,透彻理解分布式架构及其解决方案。 面向人群 1、工作1-5年需要突破瓶颈; 2、传统...

Java高级架构
2017/12/21
0
0
Dubbo集群容错和负载均衡

0、基础知识 Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。 其核心部分包含: 远程通讯: 提供对多种基于长连接的NIO框架...

Idea
01/15
0
0
dubbo源码解析-LoadBalance

前言 终于到了集群容错中的最后一个关键词,也就是,负载均衡必然会涉及一些算法.但是也不用太担心,算法这个词虽然高大上,但是算法也有简单和复杂之分.既然是源码解析类的文章,那么就有义务让看...

肥朝
2017/10/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

python模板中循环字典

{% for k,v in user.items %} {{ k}} {{ v}} {% endfor %}

南桥北木
24分钟前
0
0
Java8系列之重新认识HashMap

简介 Java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap、Hashtable、LinkedHashMap和TreeMap,类继承关系如下图所示: 下面针对各个实现类...

HOT_POT
27分钟前
0
0
获取调用方的className

/** * 获取调用方的class * @return */private static String getInvoke() { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); S......

iborder
45分钟前
0
0
深入了解一下Redis的内存模型!

一前言 Redis是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说Redis是实现网站高并发不可或缺的一部分。 我们使用Redis时,会接触Redis的5种对象类型(字符...

Java填坑之路
50分钟前
1
0
从实践出发:微服务布道师告诉你Spring Cloud与Spring Boot他如何选择

背景 随着公司业务量的飞速发展,平台面临的挑战已经远远大于业务,需求量不断增加,技术人员数量增加,面临的复杂度也大大增加。在这个背景下,平台的技术架构也完成了从传统的单体应用到微...

老道士
56分钟前
0
0
大数据学习的各个阶段

第一阶段:Linux课程讲解Linux基础操作,讲的是在命令行下进行文件系统的操作,这是Hadoop学习的基础,后面的所有视频都是基于linux操作的。鉴于很多学员没有linux基础,特增加该内容,保证零linux...

董黎明
今天
0
0
CVE-2013-0077 堆溢出分析

找了很久才发现这个环境比较容易搭建分析... 环境: 系统---Win XP SP3 漏洞程序:QQPlayer 3.7.892.400 出错DLL:quartz.dll 6.5.2600.5512 调试工具:x32db+gflag.exe 过程: 首先gflag设置...

Explorer0
今天
7
0
CISCO VPN Client Reason 442 WIN8/10错误解决方案

http://jdkleo.iteye.com/blog/2163493 引用 http://my.oschina.net/cloudcoder/blog/220391?p={{currentPage 1}} 在使用cisco VPN 客户端登录时,产生Reason 442:Failedto enable Virtual......

chenfj_fer
今天
1
0
信号量有没有容量限制?

之前一直误以为信号量初始化的时候那个初始化的值是信号量的“容量”,昨天同事指出了我的错误,最初我是不相信的,经过以下代码实践,证明了我的错误: Java版: import java.util.concurr...

锟斤拷烫烫烫
今天
1
0
【RocketMQ】Message存储笔记

概述 消息中间件存储分为三种,一是保存在内存中,速度快但会因为系统宕机等因素造成消息丢失;二是保存在内存中,同时定时将消息写入DB中,好处是持久化消息,如何读写DB是MQ的瓶颈;三是内...

SaintTinyBoy
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部