随机实现负载均衡

随机算法实现

1 最简单版本:

随机平均选择服务器

import java.util.Arrays;
import java.util.List;

public class ServerIps {

    public static final List<String> LIST = (List<String>) Arrays.asList(
            "192.168.0.1",
            "192.168.0.2",
            "192.168.0.3",
            "192.168.0.4",
            "192.168.0.5",
            "192.168.0.6",
            "192.168.0.7",
            "192.168.0.8",
            "192.168.0.9",
            "192.168.0.10"
            );

}


import java.util.Random;

public class RandomChoose{

    public static String getServer() {
        Random random = new Random();
        return ServerIps.LIST.get(random.nextInt(ServerIps.LIST.size()));
    }

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            System.out.println(getServer());
        }
    }

}

2 考虑权重的影响

但是每台机器的性能可能不同,性能强的机器能够处理更多的业务量,这种情况平均轮询不是很合理。
这样的话,需要给不同的机器设置不同的权重。

public class ServerIps {

    public static final Map<String, Integer> WEIGHT_MAP = new HashMap<>();
    static {
        WEIGHT_MAP.put("192.168.0.1", 2);
        WEIGHT_MAP.put("192.168.0.2", 8);
        WEIGHT_MAP.put("192.168.0.3", 1);
        WEIGHT_MAP.put("192.168.0.4", 9);
        WEIGHT_MAP.put("192.168.0.5", 4);
        WEIGHT_MAP.put("192.168.0.6", 6);
    }   
}

2.1 暴力解法

创建一个新的List将所有的IP地址装入List,注意根据权重来选择装入几次IP地址,比如“198.168.0.1”这个IP地址的权重是2,那么就装入2次该IP地址

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class WeightRandom{

    public static String getServer() {
        List<String> ips = new ArrayList<>();

        for(String ip: ServerIps.WEIGHT_MAP.keySet()) {
            Integer weight = ServerIps.WEIGHT_MAP.get(ip);
            for(int i=0; i<weight; i++) {
                ips.add(ip);
            }
        }
        Random random = new Random();
        return ips.get(random.nextInt(ips.size()));
    }

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            System.out.println(getServer());
        }
    }

}

2.2 优化

当权重很大的时候,将会存入很多次IP地址,耗费很大的空间
可以采用坐标映射的想法,具体如下:

其中A、B、C分别代表3个IP地址,权重分别为5、3、2 A: 5 B: 3 C: 2

映射到坐标轴为
0-----5---8--10

随意在这个坐标轴取整数就可以确定其在哪个IP地址上
如:
offset = 7
7在5---8这个区间里面,那么对应的就是B这台服务器

具体实现思路: 
offset > 5; offset - 5; offset = 2;
offset < 3;
对应B

代码实现:

import java.util.Random;

public class WeightRandom{

    public static String getServer() {

        int totalWeight = 0;
        for (Integer weight: ServerIps.WEIGHT_MAP.values()) {
            totalWeight += weight;
        }

        Random random = new Random();
        int offset = random.nextInt(totalWeight);

        for(String ip: ServerIps.WEIGHT_MAP.keySet()) {
            Integer weight = ServerIps.WEIGHT_MAP.get(ip);
            if (offset < weight) {
                return ip;
            }

            offset -= weight;
        }
        return null;

    }

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            System.out.println(getServer());
        }
    }

}

相关推荐