| 
                         ConsistentHashSelector ,是 ConsistentHashLoadBalance 的内部类,一致性哈希选择器,基于 Ketama  算法。 
- /** 
 -  * 虚拟节点与 Invoker 的映射关系 
 -  */ 
 - private final TreeMap<Long, Invoker<T>> virtualInvokers; 
 - /** 
 -  * 每个Invoker 对应的虚拟节点数 
 -  */ 
 - private final int replicaNumber; 
 - /** 
 -  * 定义哈希值 
 -  */ 
 - private final int identityHashCode; 
 - /** 
 -  * 取值参数位置数组 
 -  */ 
 - private final int[] argumentIndex; 
 -  1: ConsistentHashSelector(List<Invoker<T>> invokers, String methodName, int identityHashCode) { 
 -  2: this.virtualInvokers = new TreeMap<Long, Invoker<T>>(); 
 -  3: // 设置 identityHashCode 
 -  4: this.identityHashCode = identityHashCode; 
 -  5: URL url = invokers.get(0).getUrl(); 
 -  6: // 初始化 replicaNumber 
 -  7: this.replicaNumber = url.getMethodParameter(methodName, "hash.nodes", 160); 
 -  8: // 初始化 argumentIndex 
 -  9: String[] index = Constants.COMMA_SPLIT_PATTERN.split(url.getMethodParameter(methodName, "hash.arguments", "0")); 
 -  10: argumentIndex = new int[index.length]; 
 -  11: for (int i = 0; i < index.length; i++) { 
 -  12: argumentIndex[i] = Integer.parseInt(index[i]); 
 -  13: } 
 -  14: // 初始化 virtualInvokers 
 -  15: for (Invoker<T> invoker : invokers) { 
 -  16: String address = invoker.getUrl().getAddress(); 
 -  17: // 每四个虚拟结点为一组,为什么这样?下面会说到 
 -  18: for (int i = 0; i < replicaNumber / 4; i++) { 
 -  19: // 这组虚拟结点得到惟一名称 
 -  20: byte[] digest = md5(address + i); 
 -  21: // Md5是一个16字节长度的数组,将16字节的数组每四个字节一组,分别对应一个虚拟结点,这就是为什么上面把虚拟结点四个划分一组的原因 
 -  22: for (int h = 0; h < 4; h++) { 
 -  23: // 对于每四个字节,组成一个long值数值,做为这个虚拟节点的在环中的惟一key 
 -  24: long m = hash(digest, h); 
 -  25: virtualInvokers.put(m, invoker); 
 -  26: } 
 -  27: } 
 -  28: } 
 -  29: } 
 - public Invoker<T> select(Invocation invocation) { 
 -  // 基于方法参数,获得 KEY 
 -  String key = toKey(invocation.getArguments()); 
 -  // 计算 MD5 值 
 -  byte[] digest = md5(key); 
 -  // 计算 KEY 值 
 -  return selectForKey(hash(digest, 0)); 
 - } 
 - 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> selectForKey(long hash) { 
 -  // 得到大于当前 key 的那个子 Map ,然后从中取出第一个 key ,就是大于且离它最近的那个 key 
 -  Map.Entry<Long, Invoker<T>> entry = virtualInvokers.tailMap(hash, true).firstEntry(); 
 -  // 不存在,则取 virtualInvokers 第一个 
 -  if (entry == null) { 
 -  entry = virtualInvokers.firstEntry(); 
 -  } 
 -  // 存在,则返回 
 -  return entry.getValue(); 
 - } 
 
                          (编辑:泰州站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |