2019独角兽企业重金招聘Python工程师标准>>>

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

这篇说dubbo一致性hash负载均衡策略。要先大致了解下,什么是一直性hash算法。
一致性hash算法最早是用来解决,分布式缓存在有节点变动(新增后者删除)后,节点负载不均衡问题的。
而用一致性hash算法,就是为了达到,当集群中有节点加入或者节点删除时,尽量把负载的变化(加负,减负)均摊到每一个节点。
而没有接点变化时,一直性hash本身就是基本均衡(看hash函数)的负载策略。
基于dubbo一致性Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
我们以3个服务提供者(invoker1,invoker2,invoker3),每个invoker虚拟3个节点(v1,v2,v3),把这9个节点映射到[0,23]的值域为例
看下图:

那么dubbo认为
当一个接口方法参数(一个或者多个连接后)hash后得到的hash(key1)值19,那么它应该调用invoker2_v2节点,实际就是invoker2真实节点。
当一个接口方法参数(一个或者多个连接后)hash后得到的hash(key2)值7,那么它应该调用invoker3_v2节点,实际就是invoker3真实节点。

接下来看看具体代码实现:

/*** ConsistentHashLoadBalance** @author william.liangf*/
public class ConsistentHashLoadBalance extends AbstractLoadBalance {//接口名.方法名称为key hash选择器为value的map.每个方法一个选择器。private final ConcurrentMap<String, ConsistentHashSelector<?>> selectors = new ConcurrentHashMap<String, ConsistentHashSelector<?>>();@SuppressWarnings("unchecked")@Overrideprotected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {//接口名.方法名称为keyString key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();//取的invokers对象的hashcode,验证对象变化int identityHashCode = System.identityHashCode(invokers);//根据key获取hash选择器ConsistentHashSelector<T> selector = (ConsistentHashSelector<T>) selectors.get(key);if (selector == null || selector.identityHashCode != identityHashCode) {//选择器为null或者,对象已变化,就创建新选择器放入map中selectors.put(key, new ConsistentHashSelector<T>(invokers, invocation.getMethodName(), identityHashCode));selector = (ConsistentHashSelector<T>) selectors.get(key);}//通过选择器的select方法,返回选中的invokerreturn selector.select(invocation);}private static final class ConsistentHashSelector<T> {//hash 环(值域)中,某些值(所有虚拟节点数)到虚拟节点的映射。private final TreeMap<Long, Invoker<T>> virtualInvokers;//每个invoker 需要虚拟的节点数private final int replicaNumber;private final int identityHashCode;private final int[] argumentIndex;ConsistentHashSelector(List<Invoker<T>> invokers, String methodName, int identityHashCode) {//基于红黑树实现的有序map,有序很重要。this.virtualInvokers = new TreeMap<Long, Invoker<T>>();this.identityHashCode = identityHashCode;URL url = invokers.get(0).getUrl();//获取虚拟节点数,默认160个节点,配置例子 <dubbo:parameter key="hash.nodes" value="320" />this.replicaNumber = url.getMethodParameter(methodName, "hash.nodes", 160);//获取需要hash的参数位置。配置例子<dubbo:parameter key="hash.arguments" value="0,1" /> 默认只hash第一个,0位置参数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) {//获取提供者host:port形式地址,以160个虚拟节点为例String address = invoker.getUrl().getAddress();for (int i = 0; i < replicaNumber / 4; i++) {byte[] digest = md5(address + i);//host:port(0,1,2,3.....39),40份//每个再分别,hash 4次,(这样每个机器就虚拟了160份)for (int h = 0; h < 4; h++) {long m = hash(digest, h);//160份虚拟节点,每一份都映射同一个实际节点virtualInvokers.put(m, invoker);}}}}public Invoker<T> select(Invocation invocation) {String key = toKey(invocation.getArguments());//对拼接后的参数做MD5指纹摘要byte[] digest = md5(key);//摘要后,hash计算return selectForKey(hash(digest, 0));}/**** 把参数直接拼接。* @param args* @return*/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();}//根据hash值,选择invoker方法的核心方法private Invoker<T> selectForKey(long hash) {Invoker<T> invoker;Long key = hash;//如果key不在map里,也有可能key已在map里,直接走下面流程if (!virtualInvokers.containsKey(key)) {//方法加参数hash 参数的key,没在已近映射的ma中,//返回比key 大的map值SortedMap<Long, Invoker<T>> tailMap = virtualInvokers.tailMap(key);if (tailMap.isEmpty()) {//如果key最大,就取虚拟节点第一个(key值最小的节点)key = virtualInvokers.firstKey();} else {//取比key大的keys中,最小的一个节点,(离key最近的,大于key的节点)key = tailMap.firstKey();}}//获取key映射的实际invokerinvoker = virtualInvokers.get(key);return invoker;}
//hash 算法,也很关键private long hash(byte[] digest, int number) {//number可以是,0,1,2,3 long 类型64 bit位//最后0xFFFFFFFFL;保证4字节位表示数值。相当于Ingter型数值。所以hash环的值域是[0,Integer.max_value]//每次取digest4个字节(|操作),组成4字节的数值。//当number 为 0,1,2,3时,分别对应digest第// 1,2,3,4;// 5,6,7,8;// 9,10,11,12;// 13,14,15,16;字节//4批return ((//digest的第4(number 为 0时),8(number 为 1),12(number 为 2),16(number 为 3)字节,&0xFF后,左移24位(long) (digest[3 + number * 4] & 0xFF) << 24)|(//digest的第3,7,11,15字节,&0xFF后,左移16位(long) (digest[2 + number * 4] & 0xFF) << 16)|(//digest的第2,6,10,14字节,&0xFF后,左移8位(long) (digest[1 + number * 4] & 0xFF) << 8)|(//digest的第1,5,9,13字节,&0xFFdigest[number * 4] & 0xFF))& 0xFFFFFFFFL;}//返回16字节总共128bit位的MD5指纹签名byte[]。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;try {bytes = value.getBytes("UTF-8");} catch (UnsupportedEncodingException e) {throw new IllegalStateException(e.getMessage(), e);}md5.update(bytes);return md5.digest();}}}

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

dubbo负载均衡代码分析2(一致性hash策略)相关推荐

  1. dubbo负载均衡代码分析1(leastactive策略)

    2019独角兽企业重金招聘Python工程师标准>>> 接上篇https://my.oschina.net/u/146130/blog/1569554 既然有集群容错,自然会有负载均 ...

  2. Dubbo 负载均衡的实现

    前言 负载均衡是指在集群中,将多个数据请求分散在不同单元上进行执行,主要为了提高系统容错能力和加强系统对数据的处理能力. 在 Dubbo 中,一次服务的调用就是对所有实体域 Invoker 的一次筛选 ...

  3. dubbo负载均衡-RandomLoadBalance

    dubbo负载均衡-RandomLoadBalance 发表于 2019-10-13 前言 之前在面试中被问及dubbo的负载均衡,当时没有系统的回答出来,今天查阅了一下官方文档,于是出现了这篇文章. ...

  4. cstring只获取到第一个数_一文讲透 Dubbo 负载均衡之最小活跃数算法

    (给ImportNew加星标,提高Java技能) 作者:why技术(本文来自作者投稿) 本文是对于Dubbo负载均衡策略之一的最小活跃数算法的详细分析.文中所示源码,没有特别标注的地方均为2.6.0版 ...

  5. 一文讲透Dubbo负载均衡之最小活跃数算法

    本文是对于Dubbo负载均衡策略之一的最小活跃数算法的详细分析.文中所示源码,没有特别标注的地方均为2.6.0版本. 为什么没有用截止目前的最新的版本号2.7.4.1呢?因为2.6.0这个版本里面有两 ...

  6. Dubbo负载均衡的源码流程(2022.5.30)

    Dubbo负载均衡的源码流程 1.默认负载均衡策略:RandomLoadBalance(随机策略) 2.负载均衡策略存在以下五种: 2.1 RandomLoadBalance(随机) 2.2 Roun ...

  7. 【RPC Dubbo】dubbo负载均衡策略

    文章目录 前言 1. 什么是负载均衡 1.1:负载均衡简介 1.2:简单解释 2. dubbo负载均衡策略 2.1 Random LoadBalance 2.2 RoundRobin LoadBala ...

  8. dubbo负载均衡概念和使用

    概念 dubbo负载均衡官网介绍: 中文官网介绍的非常的详细 https://dubbo.apache.org/zh/docs/v2.7/user/examples/loadbalance/ ​ 四种 ...

  9. dubbo负载均衡。

    1.搭建zookeeper集群,搭建过程参考网上资料(地址为192.168.200.141:2182,192.168.200.141:2183,192.168.200.141:2184). 2.搭建d ...

最新文章

  1. C++中拷贝控制操作(三/五法则)
  2. 中国信通院:2019年Q1全球人工智能产业数据报告
  3. struts2拦截器底层原理
  4. 【Spring框架家族】SpringBoot基本介绍
  5. 绑定服务调用本地服务中的方法
  6. JAVA生产环境验证_Java生产环境下性能监控与调优详解
  7. linux系统中常见的目录,Linux系统中常见的目录名称以及相应内容
  8. jsf 后台参数到页面_JSF:直接从页面将参数传递给JSF操作方法,这是JavaEE 6+的一个不错的功能...
  9. 合肥python招聘_2020年合肥京东方招聘官网招聘-合肥京东方招聘官网招聘求职信息-拉勾招聘...
  10. 25 人以下,免费!
  11. 没有任何匹配: mod_auth_mysql 阿里云_文案丨网易云让人感触良多的文案
  12. mysql闩_MySQL锁概述
  13. 【Java面试题】9 abstract class和interface有什么区别?
  14. 未来计算机技术的发展趋势有哪些,浅谈计算机技术的发展趋势
  15. 微信群二维码有效期如何延长?突破7天有效期的方法!
  16. Java户籍管理系统的设计与实现
  17. c语言资料大全收集,C语言库函数大全(收集资料).pdf
  18. 对fiber的一点了解
  19. 微信号:kcctvy 所谓的专业祛荨麻疹
  20. liunx常驻运行项目命令

热门文章

  1. html5对属性布尔的值设定,如何在Javascript中设置HTML5必需属性?
  2. Python内置函数ord()与chr()
  3. word中如何优雅的显示代码
  4. python实践项目(三)
  5. 21天Jmeter打卡Day20 响应断言,JSON断言
  6. 性能测试利器 - Locust框架解析
  7. 关闭自动降频 linux,在Deepin系统下CPU不能自主降频的两种解决方法
  8. python统计词频_Python中文分词及词频统计
  9. 计算机配置扫盲,扫盲了。。怎么识别电脑配置好坏?
  10. web控制串口.html,[转]web串口调试助手,浏览器控制串口设备