直接上干活

/**
     * @version 1.0.0
     * @@menu <p>
     * @date 2020/11/17 16:28
     */
    public class LoadBlance {
        static Map<String, Integer> serverWeightMap = new HashMap<>();
    
        static {
            serverWeightMap.put("192.168.1.100", 1);
            serverWeightMap.put("192.168.1.101", 8);
            // 权重为4
            serverWeightMap.put("192.168.1.102", 4);
            serverWeightMap.put("192.168.1.103", 9);
            serverWeightMap.put("192.168.1.104", 2);
            // 权重为3
            serverWeightMap.put("192.168.1.105", 3);
            serverWeightMap.put("192.168.1.106", 4);
            // 权重为2
            serverWeightMap.put("192.168.1.107", 2);
            serverWeightMap.put("192.168.1.108", 8);
            serverWeightMap.put("192.168.1.109", 6);
            serverWeightMap.put("192.168.1.110", 1);
        }
    
        public List<String> MapCasttoList() {
            //这里重新一个map,作为缓冲, 目的是避免服务器上下线带来的问题
            Map<String, Integer> serverMap = getServerMap();
            Set<String> strings = serverMap.keySet();
            List<String> list = new ArrayList<>();
            list.addAll(strings);
            return list;
        }
    
        private Map<String, Integer> getServerMap() {
            Map<String, Integer> serverMap = new HashMap<>();
            serverMap.putAll(serverWeightMap);
            return serverMap;
        }
    
        static AtomicInteger index = new AtomicInteger();
    
        //1: 简单的轮询算法:
        public String Round() {
            List<String> ipList = MapCasttoList();
            if (index.get() >= ipList.size()) {
                index.set(0);
            }
            return ipList.get(index.getAndIncrement() % ipList.size());
        }
    
    
        //2: 随机算法
        public String RandomLoadBlance() {
            List<String> ipList = MapCasttoList();
            int index = new Random().nextInt(ipList.size());
            return ipList.get(index);
        }
    
    
        //3: ip 的hash法: 将ip hash,
        public String IpHashLoadBlance() {
            List<String> ipList = MapCasttoList();
            //获取ipList, 然后计算HashCode, 之后和 size计算出对应的index
            List<Long> ipHashList = ipList.stream().map(ip -> myHashCode(ip)).collect(Collectors.toList());
            int i = new Random().nextInt(ipList.size());
            Long index = ipHashList.get(i) % ipList.size();
            return ipList.get(index.intValue());
        }
    
        //因为 hashCode方法会出现负数,所以这里使用自写的hashCode方法
        private static long myHashCode(String str) {
            long h = 0;
            if (h == 0) {
                int off = 0;
                char val[] = str.toCharArray();
                long len = str.length();
                for (long i = 0; i < len; i++) {
                    h = 31 * h + val[off++];
                }
            }
            return h;
        }

    /**
     * 4: 一致性hash 负载轮询算法
     * 
     * 原理:  http://www.zsythink.net/archives/1182
     */
    static TreeMap<Integer, String> treeMap = new TreeMap<>();

    static {
        //这里使用的hash环,有1000个虚拟节点, 构建hash环
        List<String> serverIpList = MapCasttoList();
        for (String ip : serverIpList) {
            for (int i = 0; i < 1000; i++) {
                //这里的hash算法,是对 2 ^ 32 次方 取模
                int ipHashCode = FNVHash(ip + i);
                treeMap.put(ipHashCode, ip);
            }
        }
    }

    //str 这里的str 是指使用某个请求的标志(请求名,或者别的),来hash,最终命中hash环对应的ip
    public String consistencyHashLoadBlance(String str) {
        int hashCode = FNVHash(str);
        //找到比这个 hashCode 值大的所有子树
        SortedMap<Integer, String> tailSubMap = treeMap.tailMap(hashCode);
        if (tailSubMap == null) {
            //返回hash环的第一个节点 对应的ip
            return treeMap.get(treeMap.firstKey());
        }
        //否则返回 hash环中,这个 子树的第一个节点对应的ip
        return treeMap.get(tailSubMap.firstKey());
    }

    // 32位的 Fowler-Noll-Vo 哈希算法
    // https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
    public static int FNVHash(String key) {
        final int p = 16777619;
        Long hash = 2166136261L;
        for (int idx = 0, num = key.length(); idx < num; ++idx) {
            hash = (hash ^ key.charAt(idx)) * p;
        }
        hash += hash << 13;
        hash ^= hash >> 7;
        hash += hash << 3;
        hash ^= hash >> 17;
        hash += hash << 5;
        if (hash < 0) {
            hash = Math.abs(hash);
        }
        return hash.intValue();
    }


    
        /**
         * 5: 基于权重的轮询算法: 平滑加权轮询算法, Nginx的默认轮询算法就是 加权轮询算法
         *  
         * <p>
         * 思路: 比如 A : 5 , B : 3 , C : 2   (服务器 A,B,C 对应权重分别是 5,3,2)
         * ip: A,B,C
         * weight: 5,3,2 (计算得到 totalWeight = 10)
         * currentWeight: 0,0,0 (当前ip的初始权重都为0)
         * <p>
         * 请求次数: |  currentWeight = currentWeight + weight  |  最大权重为  |  返回的ip为 |  最大的权重 - totalWeight,其余不变
         *      1   |           5,3,2    (0,0,0 + 5,3,2)       |     5      |      A     |      -5,3,2
         *      2   |           0,6,4    (-5,3,2 + 5,3,2)      |     6      |      B     |       0,-4,4
         *      3   |           5,-1,6    (0,-4,4 + 5,3,2)     |     6      |     C      |       5,-1,-4
         *      4   |          10,2,-2    (5,-1,-4 + 5,3,2)    |     10     |     A      |       0,2,-2
         *      5   |           5,5,0                          |     5      |     A      |       -5,5,0
         *      6   |           0,8,2                          |     8      |     B      |       0,-2,2
         *      7   |           5,1,4                          |     5      |     A      |       -5,1,4
         *      8   |           0,4,6                          |     6      |     C      |       0,4,-4
         *      9   |           5,7,-2                         |     7      |     B      |       5,-3,-2
         *      10  |           10,0,0                         |     10     |     A      |        0,0,0
         * <p>
         * 至此结束: 可以看到负载轮询的策略是: A,B,C,A,A,B,A,C,B,A,
         *
         *   循环获取到权重最大的节点,和总权重, 之后将这个权重最大节点的权重 - 总权重, 最后返回这个权重最大节点对应的ip
         */
        public String weightRound(List<ServerNode> serverNodeList) {
            ServerNode selectedServerNode = null;
            int maxWeight = 0;
            int totalWeight = 0;
            for (ServerNode serverNode : serverNodeList) {
                serverNode.incrementWeight();//获取节点的当前权重
                if (serverNode.currentWeight > maxWeight) {
                    //节点的当前权重 大于最大权重, 就将该节点当做是选中的节点
                    maxWeight = serverNode.currentWeight;
                    selectedServerNode = serverNode;
                }
                //计算总的权重
                totalWeight += serverNode.weight;
            }
            // 当循环结束的时候, selectedServerNode就是权重最大的节点,对应的权重为maxWeight,  总的权重为totalWeight
            if (selectedServerNode != null) {
                //将权重最大的这个节点,的权重值减去 总权重
                selectedServerNode.decrementTotal(totalWeight);
                //并返回这个权重对应的 ip
                return selectedServerNode.ip;
            }
            return "";
        }
    
        private List<ServerNode> getServerNodeList(Map<String, Integer> serverMap) {
            List<ServerNode> list = new ArrayList<>();
            for (Map.Entry<String, Integer> entry : serverMap.entrySet()) {
                ServerNode serverNode = new ServerNode(entry.getKey(), entry.getValue());
                list.add(serverNode);
            }
            return list;
        }
    
        private class ServerNode {
            String ip;
            int weight;//初始配置好的权重
            int currentWeight;//当前的权重,初始为 0
    
            public ServerNode(String ip, int weight) {
                this.ip = ip;
                this.weight = weight;
            }
    
            public void decrementTotal(int totalWeight) {
                currentWeight = currentWeight - totalWeight;
            }
    
            public void incrementWeight() {
                currentWeight = currentWeight + weight;
            }
    
            public void setCurrentWeight(int currentWeight) {
                this.currentWeight = currentWeight;
            }
        }
    
    
    
        /**
         * 6: 加权随机
         *  思路:  1: 一个ip的权重为5, 就将这个ip存到list中五次, 然后随机,  简单,但是有缺点 list会很大,执行效率低
         *
         *  思路:  2:  转换思路: 将每一个ip的权重转化为 X轴上的数字, 随机的数字,落在X轴的那个位置, 就返回这个位置对应的 ip
         *        比如: 192.168.1.100 , 3
         *             192.168.1.102 , 6
         *             192.168.1.105 , 4
         *        转换为X轴 为: 0--3-----9---13   可以看到这里需要获取所有权重之和
         *        产生的随机数为: 12 ,
         *        12 和 第一个ip的权重3 比较, 12 >= 3
         *        然后 12 - 3 = 9, 9 和第二个ip的权重6比较, 9 >= 6
         *        然后 9 - 6 =3 , 3 和第三个ip的权重4比较, 3 < 4 跳出---->说明随机的ip 是 192.168.1.105
         *
         * 这里实现思路2
         */
        public String weightRandom(){
            //1: 获取所有ip权重之和
            List<Integer> weightList = new ArrayList<>(getServerMap().values());