首页 > 求解析这段负载均衡代码的意思

求解析这段负载均衡代码的意思

在网上搜索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 Map<String,Server>  servers = Collections.synchronizedMap(new HashMap<String, Server>());


    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<Server> servers) {
        for (int i = 0; i < servers.size(); i++) {
            Server server = servers.get(i);
            addServer(server);
        }
        LoadBalancing.initOrReload();
    }

    //查找权重,计算最大权重公约数
   public synchronized static void initOrReload(){
       Set<String> 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<String, Server> 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:以上是本人的无责任脑洞,说错了不要打我

【热门文章】
【热门文章】