dubbo的均衡策略
来源:互联网 发布:驱逐舰 知乎 编辑:程序博客网 时间:2024/05/17 21:46
RoundRobinLoadBalance
public class RoundRobinLoadBalance extends AbstractLoadBalance { public static final String NAME = "roundrobin"; private final ConcurrentMap<String, AtomicPositiveInteger> sequences = new ConcurrentHashMap<String, AtomicPositiveInteger>(); private static final class IntegerWrapper { public IntegerWrapper(int value) { this.value = value; } private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void decrement() { this.value--; } } protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) { String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName(); int length = invokers.size(); // 总个数 int maxWeight = 0; // 最大权重 int minWeight = Integer.MAX_VALUE; // 最小权重 final LinkedHashMap<Invoker<T>, IntegerWrapper> invokerToWeightMap = new LinkedHashMap<Invoker<T>, IntegerWrapper>(); int weightSum = 0; // 1.计算最大权重/最小权重/总权重 for (int i = 0; i < length; i++) { int weight = getWeight(invokers.get(i), invocation); maxWeight = Math.max(maxWeight, weight); minWeight = Math.min(minWeight, weight); if (weight > 0) { invokerToWeightMap.put(invokers.get(i), new IntegerWrapper(weight)); weightSum += weight; } } // 2.获取当前服务的调用次数,并加一返回 AtomicPositiveInteger sequence = sequences.get(key); if (sequence == null) { sequences.putIfAbsent(key, new AtomicPositiveInteger()); sequence = sequences.get(key); } int currentSequence = sequence.getAndIncrement(); // 3.取调用次数和总权重之模作为插点,轮询服务提供方 if (maxWeight > 0 && minWeight < maxWeight) { // 权重不一样 int mod = currentSequence % weightSum;// 取模 for (int i = 0; i < maxWeight; i++) { for (Map.Entry<Invoker<T>, IntegerWrapper> each : invokerToWeightMap.entrySet()) { final Invoker<T> k = each.getKey(); final IntegerWrapper v = each.getValue(); if (mod == 0 && v.getValue() > 0) { // 如果轮询到该服务方且其权重没衰减完 return k; } if (v.getValue() > 0) { // 减模,减少权重,确保权重低优先被跳过 v.decrement(); mod--; } } } } return invokers.get(currentSequence % length); }}
ConsistentHashLoadBalance
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; // 构建红黑树,存储虚拟节点,key为指定的参数的hash值,value为服务提供方 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"));// 需要hash的参数 argumentIndex = new int[index.length];// 记录需要进行hash的参数位置 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);// 对每个提供方进行加标志位后md5 for (int h = 0; h < 4; h++) { long m = hash(digest, h);// 再计算hash virtualInvokers.put(m, invoker);// 添加虚拟节点 } } } } public int getIdentityHashCode() { return identityHashCode; } // 组装入参进行hash,找到最接近入参的最小的hash值对应的服务 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(); } }}
阅读全文
0 0
- dubbo的均衡策略
- dubbo负载均衡策略
- dubbo负载均衡策略
- Dubbo负载均衡策略
- dubbo负载均衡策略(面试问题:dubbo负载均衡是怎么配置的)
- Dubbo高级篇--Dubbo负载均衡策略
- 基于Dubbo的分布式系统架构(六):Dubbo负载均衡策略
- Dubbo高级篇_09_Dubbo负载均衡策略
- Dubbo高级篇_09_Dubbo负载均衡策略
- Dubbo的负载均衡
- 阿里巴巴的分布式应用框架-dubbo负载均衡策略--- 一致哈希算法
- dubbo的4个负载均衡算法和5个cluster策略说明
- 多种多样的均衡策略
- 多种多样的均衡策略
- 多种多样的均衡策略
- 多种多样的均衡策略
- 多种多样的均衡策略
- 多种多样的均衡策略
- Lombok使用无效,个人情况解决方案
- 行为型模式之备忘录模式实现
- SimpleAdapter的使用介绍
- 单层石墨烯工业化量产科研成果及工业化量产基地落地
- C++11中<chrono>的使用
- dubbo的均衡策略
- java总结
- genymotion模拟器运行arm架构的应用出现java.lang.UnsatisfiedLinkError
- less简单的入门知识总结
- Java异常处理
- 用户注册实现方案一
- 【分析】Ceph:一个可扩展,高性能分布式文件系统
- 两个新玩意Node.js+LESS
- 等差数列