LoadBalancedDemo
1 package com.miaoshaproject; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 /** 9 * @Author wangshuo 10 * @Date 2022/6/16, 20:07 11 * node参数: 12 * weight: 配置文件中指定的该后端的权重,这个值是固定不变的。 13 * effective_weight: 后端的有效权重,初始值为weight,程序报错后减一。 14 * current_weight: 后端目前的权重,一开始为0,之后会动态调整 15 */ 16 public class LoadBalancedDemo { 17 18 //调用接口 19 public interface Invoker { 20 Boolean isAvailable(); 21 String id(); 22 } 23 //约定的invoker和权重的键值对 24 final private List<Node> nodes; 25 private static class Node implements Comparable<Node> { 26 final Invoker invoker; 27 final Integer weight; 28 Integer effectiveWeight; 29 Integer currentWeight; 30 31 Node(Invoker invoker, Integer weight) { 32 this.invoker = invoker; 33 this.weight = weight; 34 this.effectiveWeight = weight; 35 this.currentWeight = 0; 36 } 37 38 @Override 39 public int compareTo(Node o) { 40 return currentWeight > o.currentWeight ? 1 : (currentWeight.equals(o.currentWeight) ? 0 : -1); 41 } 42 43 public void onInvokeSuccess() { 44 if (effectiveWeight < this.weight) 45 effectiveWeight++; 46 } 47 48 public void onInvokeFail() { 49 effectiveWeight--; 50 } 51 } 52 53 //构造 54 public LoadBalancedDemo(Map<Invoker, Integer> invokersWeight) { 55 if (invokersWeight != null && !invokersWeight.isEmpty()) { 56 nodes = new ArrayList<>(invokersWeight.size()); 57 invokersWeight.forEach((invoker, weight) -> nodes.add(new Node(invoker, weight))); 58 } else 59 nodes = null; 60 } 61 62 /** 63 * 算法逻辑: 64 * 1. 对于每个请求,遍历集群中的所有可用后端,对于每个后端peer执行: 65 * peer->current_weight += peer->effective_weight。 66 * 同时累加所有peer的effective_weight,保存为total。 67 * 2. 从集群中选出current_weight最大的peer,作为本次选定的后端。 68 * 3. 对于本次选定的后端,执行:peer->current_weight -= total。 69 * 70 */ 71 public Invoker select() { 72 if (!checkNodes()) 73 return null; 74 else if (nodes.size() == 1) { 75 if (nodes.get(0).invoker.isAvailable()) 76 return nodes.get(0).invoker; 77 else 78 return null; 79 } 80 Integer total = 0; 81 Node nodeOfMaxWeight = null; 82 for (Node node : nodes) { 83 total += node.effectiveWeight; 84 node.currentWeight += node.effectiveWeight; 85 86 if (nodeOfMaxWeight == null) { 87 nodeOfMaxWeight = node; 88 } else { 89 nodeOfMaxWeight = nodeOfMaxWeight.compareTo(node) > 0 ? nodeOfMaxWeight : node; 90 } 91 } 92 93 nodeOfMaxWeight.currentWeight -= total; 94 return nodeOfMaxWeight.invoker; 95 } 96 97 public void onInvokeSuccess(Invoker invoker) { 98 if (checkNodes()) { 99 nodes.stream() 100 .filter((Node node) -> invoker.id().equals(node.invoker.id())) 101 .findFirst() 102 .get() 103 .onInvokeSuccess(); 104 } 105 } 106 107 public void onInvokeFail(Invoker invoker) { 108 if (checkNodes()) { 109 nodes.stream() 110 .filter((Node node) -> invoker.id().equals(node.invoker.id())) 111 .findFirst() 112 .get() 113 .onInvokeFail(); 114 } 115 } 116 117 private boolean checkNodes() { 118 return (nodes != null && nodes.size() > 0); 119 } 120 121 public void printCurrentWeightBeforeSelect() { 122 if (checkNodes()) { 123 final StringBuffer out = new StringBuffer("{"); 124 nodes.forEach(node -> out.append(node.invoker.id()) 125 .append("=") 126 .append(node.currentWeight + node.effectiveWeight) 127 .append(",")); 128 out.append("}"); 129 System.out.print(out); 130 } 131 } 132 133 public void printCurrentWeight() { 134 if (checkNodes()) { 135 final StringBuffer out = new StringBuffer("{"); 136 nodes.forEach(node -> out.append(node.invoker.id()) 137 .append("=") 138 .append(node.currentWeight) 139 .append(",")); 140 out.append("}"); 141 System.out.print(out); 142 } 143 } 144 145 static Invoker initialize(String str){ 146 return new Invoker() { 147 @Override 148 public Boolean isAvailable() { 149 return true; 150 } 151 @Override 152 public String id() { 153 return str; 154 } 155 }; 156 } 157 158 public static void main(String[] args) { 159 //new实验数据 160 Map<Invoker, Integer> invokersWeight = new HashMap<>(3); 161 invokersWeight.put(initialize("a"), 4); 162 invokersWeight.put(initialize("b"), 2); 163 invokersWeight.put(initialize("c"), 1); 164 int times = 7; 165 //test start 166 LoadBalancedDemo roundRobin = new LoadBalancedDemo(invokersWeight); 167 for (int i = 1; i <= times; i++) { 168 System.out.print("第" + i + "次请求 选中前数据"); 169 roundRobin.printCurrentWeightBeforeSelect(); 170 Invoker invoker = roundRobin.select(); 171 System.out.print(" 本次选中" + invoker.id() + " 选中后数据"); 172 roundRobin.printCurrentWeight(); 173 System.out.println(); 174 } 175 } 176 }
本文来自博客园,作者:荣慕平,转载请注明原文链接:https://www.cnblogs.com/rongmuping/articles/16383563.html