• dubbo 4 负载均衡


    一  背景

    Dubbo是一个分布式服务框架,能避免单点故障和支持服务的横向扩容。一个服务通常会部署多个实例。如何从多个服务 Provider 组成的集群中挑选出一个进行调用,就涉及到一个负载均衡的策略。

    二 Dubbo内置负载均衡策略

    Dubbo内置了4种负载均衡策略:

    1. Random:随机负载均衡。随机的选择一个。是Dubbo的默认负载均衡策略。
    2. RoundRobin:轮询负载均衡。轮询选择一个。
    3. LeastActive:最少活跃调用数,这个active数目就是表示,某个方法当前有多少调用数正在执行(开始调用,但还没有返回)。相同活跃数的随机。活跃数指调用前后计数差。使慢的 Provider 收到更少请求,因为越慢的 Provider 的调用前后计数差会越大。
    4. ConsistentHash:一致性哈希负载均衡。相同参数的请求总是落在同一台机器上。

    1.随机负载均衡  Random

        随机负载均衡策略就是从多个 Provider 中随机选择一个。但是 Dubbo 中的随机负载均衡有一个权重的概念,即按照权重设置随机概率。比如说,有10个 Provider,并不是说,每个 Provider 的概率都是一样的,而是要结合这10个 Provider 的权重来分配概率。

    Dubbo中,可以对 Provider 设置权重。比如机器性能好的,可以设置大一点的权重,性能差的,可以设置小一点的权重。权重会对负载均衡产生影响。可以在Dubbo Admin中对 Provider 进行权重的设置。

    随机负载均衡源码

    基于权重来随机选择。权重越大的,被选中的概率越大
    public class RandomLoadBalance extends AbstractLoadBalance {
    
        private final Random random = new Random();
    
        protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
            int length = invokers.size();      // Invoker 总数
            int totalWeight = 0;               // 所有 Invoker 的权重的和
    
            // 判断是不是所有的 Invoker 的权重都是一样的
            // 如果权重都一样,就简单了。直接用Random生成索引就可以了。
            boolean sameWeight = true;
            for (int i = 0; i < length; i++) {
                int weight = getWeight(invokers.get(i), invocation);
                totalWeight += weight; // Sum
                if (sameWeight && i > 0 && weight != getWeight(invokers.get(i - 1), invocation)) {
                    sameWeight = false;
                }
            }
    
            if (totalWeight > 0 && !sameWeight) {
                // 如果不是所有的 Invoker 权重都相同,那么基于权重来随机选择。权重越大的,被选中的概率越大
                int offset = random.nextInt(totalWeight);
                for (int i = 0; i < length; i++) {
                    offset -= getWeight(invokers.get(i), invocation);
                    if (offset < 0) {
                        return invokers.get(i);
                    }
                }
            }
            // 如果所有 Invoker 权重相同
            return invokers.get(random.nextInt(length));
        }
    }

    2 轮询负载均衡  RoundRobin

        就是依次的调用所有的 Provider。和随机负载均衡策略一样,轮询负载均衡策略也有权重的概念。 轮询负载均衡算法可以让RPC调用严格按照我们设置的比例来分配。不管是少量的调用还是大量的调用。但是轮询负载均衡算法也有不足的地方,存在慢的 Provider 累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上,导致整个系统变慢。

    3.最少活跃调用数负载均衡

    最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差,使慢的机器收到更少。

         这个解释好像说的不是太明白。目的是让更慢的机器收到更少的请求,但具体怎么实现的还是不太清楚。举个例子:每个服务维护一个活跃数计数器。当A机器开始处理请求,该计数器加1,此时A还未处理完成。若处理完毕则计数器减1。而B机器接受到请求后很快处理完毕。那么A,B的活跃数分别是1,0。当又产生了一个新的请求,则选择B机器去执行(B活跃数最小),这样使慢的机器A收到少的请求。

    4.一致性Hash算法

    概述:

    如果采用常用的hash(object)%N算法,那么在有机器添加或者删除后,映射关系就变了,很多原有的缓存就无法找到了

    一致性hash:添加删除机器前后映射关系一致,当然,不是严格一致。实现的关键是环形Hash空间。将数据和机器都hash到环上,数据映射到顺时针离自己最近的机器中。

     一致性hash单调性体现在: 
    无论是新增主机还是删除主机,被影响的都是离那台主机最近的那些节点,其他节点映射关系没有影响

    使用一致性 Hash 算法,让相同参数的请求总是发到同一 Provider。 当某一台 Provider 崩溃时,原本发往该 Provider 的请求,基于虚拟节点,平摊到其它 Provider,不会引起剧烈变动

    缺省只对第一个参数Hash,如果要修改,请配置:

    <dubbo:parameter key="hash.arguments" value="0,1" />
    

    缺省用160份虚拟节点,如果要修改,请配置:

    <dubbo:parameter key="hash.nodes" value="320" />
    

    优点:一致性Hash算法可以和缓存机制配合起来使用。比如有一个服务getUserInfo(String userId)。设置了Hash算法后,相同的userId的调用,都会发送到同一个 Provider。这个 Provider 上可以把用户数据在内存中进行缓存,减少访问数据库或分布式缓存的次数。如果业务上允许这部分数据有一段时间的不一致,可以考虑这种做法。减少对数据库,缓存等中间件的依赖和访问次数,同时减少了网络IO操作,提高系统性能。

    三  负载均衡配置

    如果不指定负载均衡,默认使用随机负载均衡。我们也可以根据自己的需要,显式指定一个负载均衡。 可以在多个地方类来配置负载均衡,比如 Provider 端,Consumer端,服务级别,方法级别等。

    服务端服务级别

    <dubbo:service interface="..." loadbalance="roundrobin" />
    

    该服务的所有方法都使用roundrobin负载均衡。

    客户端服务级别

    <dubbo:reference interface="..." loadbalance="roundrobin" />
    

    该服务的所有方法都使用roundrobin负载均衡。

    服务端方法级别

    <dubbo:service interface="...">
        <dubbo:method name="hello" loadbalance="roundrobin"/>
    </dubbo:service>
    

    只有该服务的hello方法使用roundrobin负载均衡。

    客户端方法级别

    <dubbo:reference interface="...">
        <dubbo:method name="hello" loadbalance="roundrobin"/>
    </dubbo:reference>
    

    只有该服务的hello方法使用roundrobin负载均衡。

    和Dubbo其他的配置类似,多个配置是有覆盖关系的:

    1. 方法级优先,接口级次之,全局配置再次之。
    2. 如果级别一样,则消费方优先,提供方次之。

    所以,上面4种配置的优先级是:

    1. 客户端方法级别配置。
    2. 客户端接口级别配置。
    3. 服务端方法级别配置。
    4. 服务端接口级别配置。
  • 相关阅读:
    面向领域的微服务架构
    java常用工具类
    java字节码解析
    详解 Java 内部类
    MongoDB配置教程
    oracle18c相关
    VBS编辑文件夹下所有excel文档
    oracle新增主键
    sqlldr加载字符问题
    ora-00257
  • 原文地址:https://www.cnblogs.com/hup666/p/13466421.html
Copyright © 2020-2023  润新知