`
qq466862016
  • 浏览: 128425 次
  • 来自: 杭州
社区版块
存档分类
最新评论

阿里巴巴的分布式应用框架-dubbo负载均衡策略--- 一致哈希算法

阅读更多

               dubbo负载均衡策略一致哈希算法源码

    dubbo是阿里巴巴公司开发的一个开源分布式应用框架,基于服务的发布者和订阅者,服务者启动服务向注册中心发布自己的服务;消费者(订阅者)启动服务器向注册中心订阅所需要的服务。注册中心将订阅的服务注册列表返回给订阅者。注册中心会感应服务的提供者的变化,如果服务的提供者发生变化,注册中心会立即通知消费者及时变更服务信息数据;dubbo并且带有审计功能--监控中心,服务的发布者和服务的消费者每分钟间隔都会向监控中心发送自己的统计情况如:调用次数 或者调用时间等(这些数据是保存在内存中以每分钟为单位向监控中心进行发送数据)。监控中心宕机不影响使用,只是减少部分采样的数据,对等的集群任意一台服务宕机,会自动切换到其他对等的机器,注册中心宕机,对服务没有影响,订阅者自己本地会缓存服务提供者的列表信息,由此可见dubbo的健壮性还是可以的。

       dubbo有很多非常好的特性:负载均衡、集群容错等

集群容错策略:

failover :失败重连;

failfast:只发起一次请求;

failsafe:失败直接忽略;

failback:失败返回定时发送;、

forking:并发执行 只要有一台成功立即返回;

broadcast:调用所有提供者任意一台报错就报错)。

 

负载均衡:

 

  随机按照权重概率选择

  轮循,按公约后的权重设置轮循比率

  • 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
  • 一致哈希:相同的请求参数会请求同一个服务提供者。

支持多协议:

dubbo、thrift、rmi、jms、redis 等。

 

下面我们看下dubbo的一直哈希策略的实现源代码:默认有160个虚拟节点 这样让服务列表更加均匀分布,命中更均匀。

    

/*
 * Copyright 1999-2012 Alibaba Group.
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.dubbo.rpc.cluster.loadbalance;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;

/**
 * ConsistentHashLoadBalance
 * 
 * @author william.liangf
 */
public class ConsistentHashLoadBalance extends AbstractLoadBalance {

    private final ConcurrentMap<String, ConsistentHashSelector<?>> selectors = new ConcurrentHashMap<String, ConsistentHashSelector<?>>();

    @SuppressWarnings("unchecked")
    @Override
    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
        int identityHashCode = System.identityHashCode(invokers);
        ConsistentHashSelector<T> selector = (ConsistentHashSelector<T>) selectors.get(key);
        if (selector == null || selector.getIdentityHashCode() != identityHashCode) {
            selectors.put(key, new ConsistentHashSelector<T>(invokers, invocation.getMethodName(), identityHashCode));
            selector = (ConsistentHashSelector<T>) selectors.get(key);
        }
        return selector.select(invocation);
    }

    private static final class ConsistentHashSelector<T> {

        private final TreeMap<Long, Invoker<T>> virtualInvokers;

        private final int                       replicaNumber;
        
        private final int                       identityHashCode;
        
        private final int[]                     argumentIndex;

        public ConsistentHashSelector(List<Invoker<T>> invokers, String methodName, int identityHashCode) {
            this.virtualInvokers = new TreeMap<Long, Invoker<T>>();
            this.identityHashCode = System.identityHashCode(invokers);
            URL url = invokers.get(0).getUrl();
            this.replicaNumber = url.getMethodParameter(methodName, "hash.nodes", 160);
            String[] index = Constants.COMMA_SPLIT_PATTERN.split(url.getMethodParameter(methodName, "hash.arguments", "0"));
            argumentIndex = new int[index.length];
            for (int i = 0; i < index.length; i ++) {
                argumentIndex[i] = Integer.parseInt(index[i]);
            }
            for (Invoker<T> invoker : invokers) {
                for (int i = 0; i < replicaNumber / 4; i++) {
                    byte[] digest = md5(invoker.getUrl().toFullString() + i);
                    for (int h = 0; h < 4; h++) {
                        long m = hash(digest, h);
                        virtualInvokers.put(m, invoker);
                    }
                }
            }
        }

        public int getIdentityHashCode() {
            return identityHashCode;
        }

        public Invoker<T> select(Invocation invocation) {
            String key = toKey(invocation.getArguments());
            byte[] digest = md5(key);
            Invoker<T> invoker = sekectForKey(hash(digest, 0));
            return invoker;
        }

        private String toKey(Object[] args) {
            StringBuilder buf = new StringBuilder();
            for (int i : argumentIndex) {
                if (i >= 0 && i < args.length) {
                    buf.append(args[i]);
                }
            }
            return buf.toString();
        }

        private Invoker<T> sekectForKey(long hash) {
            Invoker<T> invoker;
            Long key = hash;
            if (!virtualInvokers.containsKey(key)) {
                SortedMap<Long, Invoker<T>> tailMap = virtualInvokers.tailMap(key);
                if (tailMap.isEmpty()) {
                    key = virtualInvokers.firstKey();
                } else {
                    key = tailMap.firstKey();
                }
            }
            invoker = virtualInvokers.get(key);
            return invoker;
        }

        private long hash(byte[] digest, int number) {
            return (((long) (digest[3 + number * 4] & 0xFF) << 24)
                    | ((long) (digest[2 + number * 4] & 0xFF) << 16)
                    | ((long) (digest[1 + number * 4] & 0xFF) << 8) 
                    | (digest[0 + number * 4] & 0xFF)) 
                    & 0xFFFFFFFFL;
        }

        private byte[] md5(String value) {
            MessageDigest md5;
            try {
                md5 = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
            md5.reset();
            byte[] bytes = null;
            try {
                bytes = value.getBytes("UTF-8");
            } catch (UnsupportedEncodingException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
            md5.update(bytes);
            return md5.digest();
        }

    }

}

 

 

2
4
分享到:
评论

相关推荐

    Dubbo负载均衡策略.docx

    在分布式服务架构中,Dubbo作为一个高性能、轻量级的Java RPC框架,其核心功能之一就是提供服务的负载均衡策略。负载均衡的主要目的是在多台服务器之间合理分配请求,以达到优化资源使用、提高系统吞吐量、降低响应...

    Dubbo-负载均衡算法.docx

    Dubbo作为一个广泛使用的微服务框架,提供了多种负载均衡策略来支持服务间的调用分发。这些策略包括Random LoadBalance(随机均衡算法)、RoundRobin LoadBalance(权重轮询均衡算法)、LeastAction LoadBalance...

    Dubbo服务集群的负载均衡算法

    【Dubbo服务集群的负载均衡算法】是分布式系统中用于优化资源分配的重要机制,它确保了请求能够均匀地分摊到各个服务提供者上,从而提高系统的稳定性和响应效率。Dubbo作为一款流行的Java微服务框架,内置了四种负载...

    Dubbo的负载均衡算法.docx

    在分布式服务框架Dubbo中,负载均衡算法是核心功能之一,用于在集群中均匀分配请求,确保服务的稳定性和高效性。Dubbo提供了四种负载均衡策略,分别是Random LoadBalance(随机算法)、RoundRobin LoadBalance(权重...

    dubbo服务限流与负载均衡

    在分布式服务架构中,Dubbo作为一个高性能、轻量级的服务框架,其服务限流与负载均衡功能至关重要。这两个特性能够确保系统的稳定性和高可用性,防止过载导致服务崩溃,并优化资源分配,提升整体系统性能。 一、...

    java面试——Dubbo面试专题.zip

    - Dubbo内置策略:介绍随机、轮询、最少活跃调用数、一致性哈希等负载均衡算法,并讨论在不同场景下的适用性。 6. **容错机制** - Fallback与Retry:理解服务调用失败后的处理策略,如FallBack回调和重试机制。 ...

    Java 轻量级的集群负载均衡设计

    - **Dubbo**:阿里巴巴开源的服务治理框架,包括负载均衡功能。 - **Zookeeper**:用于分布式协调,可以用来管理服务器列表和负载均衡策略。 总的来说,通过学习和实践"Java 轻量级的集群负载均衡设计"项目,你可以...

    35_dubbo支持哪些负载均衡、高可用以及动态代理的策略?.zip

    Dubbo是中国阿里巴巴开源的一款高性能、轻量级的Java服务框架,它提供了丰富的功能,包括服务治理、集群容错、负载均衡、动态配置等。在这个主题中,我们将详细探讨Dubbo支持的负载均衡策略、高可用方案以及动态代理...

    BAT面试题大全进大厂必看358页精品,2022年最新资源,助您斩获offer!

    Dubbo是一个高性能、轻量级的Java RPC框架,由阿里巴巴开发并维护,广泛应用于大型互联网公司,如BAT(百度、阿里巴巴、腾讯)等。了解和掌握Dubbo的相关知识对于进入大厂面试至关重要。 1. **为什么要用Dubbo?** ...

    2013 阿里巴巴面试题

    4. **分布式系统**:阿里巴巴作为电商巨头,分布式计算、分布式存储、分布式服务框架(如Dubbo、HSF)是核心技术。面试可能涉及CAP定理、分布式一致性、负载均衡、分布式锁等概念。 5. **网络协议与安全**:TCP/IP...

    java面试知识点整理.zip

    这些知识点涵盖了多线程、Spring框架、Spring Cloud、JVM优化、Redis缓存、消息队列(MQ)、Kafka、Dubbo、算法、设计模式以及分布式系统等多个领域。下面,我们将详细讨论这些领域的核心概念和重要知识点。 1. **...

    Dubbo面试40问及参考答案.docx

    - **策略种类**:Dubbo支持多种负载均衡策略,如随机(Random)、轮询(RoundRobin)、最少活跃调用数(LeastActive)、一致性哈希(ConsistentHash)等。 - **默认策略**:默认使用随机策略。 #### 17. 服务多协议...

    Dubbo服务框架面试专题及答案整理文档.zip

    Dubbo作为阿里巴巴开源的高性能、轻量级的服务治理框架,广泛应用于分布式系统开发中。这份文档涵盖了Dubbo的核心概念、功能、设计模式以及常见面试问题的答案,下面我们将详细探讨其中的知识点。 1. **Dubbo基础**...

    dubbo开发者指南

    Dubbo由阿里巴巴开源,是Java世界中广泛使用的分布式服务框架,它强调了服务的注册与发现、负载均衡、容错以及性能监控等核心功能。 一、Dubbo简介 Dubbo是一个基于Java的RPC(Remote Procedure Call)框架,其主要...

    zookeeper实现分布式session sample

    - Zookeeper是一个分布式服务框架,主要用于解决分布式应用中的数据一致性问题。 - 它提供了一种树形的数据结构,节点称为Znode,每个Znode可以存储数据并有唯一的路径标识。 - Zookeeper提供了多种watch机制,...

    基于Dubbo的跨语言服务治理框架.pdf

    1. **负载均衡策略**:Dubbo提供了多种负载均衡策略,如随机(RandomLoadBalance)、最小活跃数(LeastActiveLoadBalance)、一致性哈希(ConsistentHashLoadBalance)和加权轮询(RoundRobinLoadBalance)。...

    阿里巴巴 java笔试 试题 有两份

    在实际问题解决能力上,面试官可能还会询问关于分布式系统、微服务架构、数据库设计(SQL查询优化)、负载均衡、缓存策略等方面的问题,以检验候选人在复杂业务场景下的应对能力。 最后,对于2010年的校园笔试题目...

    分布式常见的面试题(java)

    5. Dubbo:Dubbo是阿里巴巴的高性能Java RPC框架,面试时可能会涉及服务注册与发现,调用协议(如Dubbo、HTTP、REST),负载均衡策略,服务治理(如熔断、降级、限流),以及Spring Cloud与Dubbo的对比。 6. 分布式...

    Dubbo面试题(2022最新版)

    Dubbo是一款高性能、轻量级的开源RPC框架,它支持多种通信协议和序列化方式,具备服务自动注册、服务发现、软负载均衡等功能,能够有效管理和优化大型分布式系统的服务交互。 3. **Dubbo的使用场景有哪些?** - ...

Global site tag (gtag.js) - Google Analytics