在网上搜索JAVA负载均衡算法,大多是这篇代码。
public class LoadBalancing { private final static String SERVER_MASTER = "master" ; private final static String SERVER_SLAVE = "slave" ; //上一次,选择服务器的编号 private static Integer currentIndex = -1; //当前权重 private static Integer currentWeight = 0; //最大权重 private static Integer maxWeight = 0; //最大权重公约数 private static Integer gcdWeight = 0; //主服务器 private static Server master; //服务器集合 private static Mapservers = Collections.synchronizedMap(new HashMap ()); public static Integer getCurrentIndex() { return currentIndex; } public static Integer getCurrentWeight() { return currentWeight; } public static Integer getMaxWeight() { return maxWeight; } public static Server getMaster() { return master; } public static void setMaster(Server master) { LoadBalancing.master = master; } public static Integer getGcdWeight() { return gcdWeight; } //添加服务器 public static void addServer(Server server){ if(server==null){ throw new RuntimeException("error:server is nullable!"); } int index = servers.size(); servers.put(String.valueOf(index),server); if(server.getType()!=null&&SERVER_MASTER.equals(server.getType())){ servers.put(SERVER_MASTER,server); }else if(server.getType()==null){ server.setType(SERVER_SLAVE); } } //添加服务器 public static void addServer(List servers) { for (int i = 0; i < servers.size(); i++) { Server server = servers.get(i); addServer(server); } LoadBalancing.initOrReload(); } //查找权重,计算最大权重公约数 public synchronized static void initOrReload(){ Set keys = servers.keySet(); Server prev_server = null ; for(String key:keys){ Server server = servers.get(key); if(prev_server!=null){ gcdWeight = new BigInteger(String.valueOf(prev_server.getWeight())).gcd(new BigInteger(String.valueOf(prev_server.getWeight()))).intValue(); } if(server.getWeight()>maxWeight){ maxWeight = server.getWeight(); } prev_server = server; } if(master==null){ master = servers.get("0"); master.setType(SERVER_MASTER); servers.put(SERVER_MASTER,master); } } //轮询服务器 public static Server getServer(){ int count = 0; int size = servers.size(); while (true){ currentIndex = (currentIndex+1)%size; if(currentIndex==0){ currentWeight = currentWeight - gcdWeight; if (currentWeight <= 0) { currentWeight = maxWeight; } } Server server = servers.get(String.valueOf(currentIndex)); if(server!=null&&server.getWeight()>=currentWeight&&!server.isDown){ server.addAccessCount(); return server; } if(count>=size){ if(master.isDown){ new RuntimeException("error:master is down!"); } return master; } count++; } } public static Map getServers() { return servers; } public static class Server { //服务器编号 private String id; ///服务器ip private String ip; //权重 private int weight; //类型,主从 private String type; //访问数量 private Integer accessCount = 0; //是否脱机 private boolean isDown; public Server(String ip, int weight) { this.ip = ip; this.weight = weight; } public int getAccessCount() { return accessCount; } public void setAccessCount(int accessCount) { this.accessCount = accessCount; } public void addAccessCount() { synchronized (this.accessCount){ this.accessCount++; } } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public boolean isDown() { return isDown; } public void setDown(boolean down) { if((this.isDown&&down)||(!this.isDown&&!down)){ return; }else{ //移除或恢复操作 initOrReload(); } isDown = down; } } }
请大神给我讲讲initOrReload方法中,最大权重公约数的作用是什么?为什么要求prev_server自己的公约数呢?
另外再跟我讲讲getServer方法。
1.个人想法
gcdWeight = new BigInteger(String.valueOf(prev_server.getWeight())).gcd(new BigInteger(String.valueOf(prev_server.getWeight()))).intValue(); }
后面应该是笔误,后面的 prev_server应该改为 server
2.最大权重公约数可以保证两点:A.性能高的服务器优先使用(权重代表性能) B.能够平衡不同服务器的性能差别
我们结合 getServer 来看
假设有一组服务器的权重是 6,8,10,12
初始化后, gcdWeight=2 currentIndex=-1 currentWeight=0 maxWeight=12
执行 getServer 第一次轮询: currentWeight = currentWeight-gcdWeight < 0 currentWeight = maxWeight = 12 所以将权重为12的服务器分配出去,现在剩下 [6,8,10] 三台服务器 第二次轮询: currentWeight = currentWeight-gcdWeight = 10 将权重为10的服务器拉出去,剩下服务器[6,8] 第三次轮询: 将server[8]拉出去 第四次轮询: 将server[6]拉出去 结束
你看,当服务器之间的权重差别比较平衡(某个值的K倍)时,按照高性能优先的原则依次分配服务器
那么,如果服务器之间的权重差别不平衡呢?
现在假设另一组服务器的权重为 6,8,9,12
初始化后, gcdWeight=1 currentIndex=-1 currentWeight=0 maxWeight=12
执行 getServer 第一次轮询: currentWeight = currentWeight-gcdWeight < 0 currentWeight = maxWeight = 12 所以将权重为12的服务器分配出去,现在剩下 [6,8,9] 三台服务器 第二次轮询: currentWeight = currentWeight-gcdWeight = 11 剩下的服务器权重都比11小,因此只能使用主服务器(master) 第三次轮询: currentWeight = currentWeight-gcdWeight = 10 剩下的服务器权重都比10小,因此只能使用主服务器(master) 第四次轮询: currentWeight = currentWeight-gcdWeight = 9 权重为9的服务器分配出去 第五次轮询: currentWeight = currentWeight-gcdWeight = 8 权重为8的服务器分配出去 第六次轮询: currentWeight = currentWeight-gcdWeight = 7 剩下的服务器权重比7小,因此只能使用主服务器(master) 第七次轮询: 权重为6的服务器分配出去 结束
你看,当服务器之间的性能差异不平衡时,会多使用几次主服务器(性能应该是最好的),这样一来就能保证整体服务器的性能是平衡的
所以,这种基于权重轮询的负载均衡算法,既能保证性能高的服务器优先使用,又能最大程度平衡不同服务器之间的性能差别,真的是exciting
PS:以上是本人的无责任脑洞,说错了不要打我