设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 手机 数据 公司
当前位置: 首页 > 服务器 > 搭建环境 > Windows > 正文

谈谈Dubbo负载均衡是如何实现的?(4)

发布时间:2019-09-10 12:09 所属栏目:117 来源:程序员界的彭于晏
导读:ConsistentHashSelector ,是 ConsistentHashLoadBalance 的内部类,一致性哈希选择器,基于 Ketama 算法。 /** *虚拟节点与Invoker的映射关系 */ privatefinalTreeMapLong,InvokerTvirtualInvokers; /** *每个Invo

ConsistentHashSelector ,是 ConsistentHashLoadBalance 的内部类,一致性哈希选择器,基于 Ketama 算法。

  1. /** 
  2.  * 虚拟节点与 Invoker 的映射关系 
  3.  */ 
  4. private final TreeMap<Long, Invoker<T>> virtualInvokers; 
  5. /** 
  6.  * 每个Invoker 对应的虚拟节点数 
  7.  */ 
  8. private final int replicaNumber; 
  9. /** 
  10.  * 定义哈希值 
  11.  */ 
  12. private final int identityHashCode; 
  13. /** 
  14.  * 取值参数位置数组 
  15.  */ 
  16. private final int[] argumentIndex; 
  17.  1: ConsistentHashSelector(List<Invoker<T>> invokers, String methodName, int identityHashCode) { 
  18.  2: this.virtualInvokers = new TreeMap<Long, Invoker<T>>(); 
  19.  3: // 设置 identityHashCode 
  20.  4: this.identityHashCode = identityHashCode; 
  21.  5: URL url = invokers.get(0).getUrl(); 
  22.  6: // 初始化 replicaNumber 
  23.  7: this.replicaNumber = url.getMethodParameter(methodName, "hash.nodes", 160); 
  24.  8: // 初始化 argumentIndex 
  25.  9: String[] index = Constants.COMMA_SPLIT_PATTERN.split(url.getMethodParameter(methodName, "hash.arguments", "0")); 
  26.  10: argumentIndex = new int[index.length]; 
  27.  11: for (int i = 0; i < index.length; i++) { 
  28.  12: argumentIndex[i] = Integer.parseInt(index[i]); 
  29.  13: } 
  30.  14: // 初始化 virtualInvokers 
  31.  15: for (Invoker<T> invoker : invokers) { 
  32.  16: String address = invoker.getUrl().getAddress(); 
  33.  17: // 每四个虚拟结点为一组,为什么这样?下面会说到 
  34.  18: for (int i = 0; i < replicaNumber / 4; i++) { 
  35.  19: // 这组虚拟结点得到惟一名称 
  36.  20: byte[] digest = md5(address + i); 
  37.  21: // Md5是一个16字节长度的数组,将16字节的数组每四个字节一组,分别对应一个虚拟结点,这就是为什么上面把虚拟结点四个划分一组的原因 
  38.  22: for (int h = 0; h < 4; h++) { 
  39.  23: // 对于每四个字节,组成一个long值数值,做为这个虚拟节点的在环中的惟一key 
  40.  24: long m = hash(digest, h); 
  41.  25: virtualInvokers.put(m, invoker); 
  42.  26: } 
  43.  27: } 
  44.  28: } 
  45.  29: } 
  46. public Invoker<T> select(Invocation invocation) { 
  47.  // 基于方法参数,获得 KEY 
  48.  String key = toKey(invocation.getArguments()); 
  49.  // 计算 MD5 值 
  50.  byte[] digest = md5(key); 
  51.  // 计算 KEY 值 
  52.  return selectForKey(hash(digest, 0)); 
  53. private String toKey(Object[] args) { 
  54.  StringBuilder buf = new StringBuilder(); 
  55.  for (int i : argumentIndex) { 
  56.  if (i >= 0 && i < args.length) { 
  57.  buf.append(args[i]); 
  58.  } 
  59.  } 
  60.  return buf.toString(); 
  61. private Invoker<T> selectForKey(long hash) { 
  62.  // 得到大于当前 key 的那个子 Map ,然后从中取出第一个 key ,就是大于且离它最近的那个 key 
  63.  Map.Entry<Long, Invoker<T>> entry = virtualInvokers.tailMap(hash, true).firstEntry(); 
  64.  // 不存在,则取 virtualInvokers 第一个 
  65.  if (entry == null) { 
  66.  entry = virtualInvokers.firstEntry(); 
  67.  } 
  68.  // 存在,则返回 
  69.  return entry.getValue(); 

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读