1、随机轮循算法
随机算法的实现很简单,我们可以直接通过Random的nextInt()方法实现一个加权随机算法,这种方式在日常的开发工作中还是很常用到的。
我们首先定义一个ServerIps类,用来存放所有服务IP值
public class ServerIps { public static final List<String> LIST = 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" ); }
然后我们创建类LoadBalance来实现随机算法
public class LoadBalance { public static String getServer(){ Random random = new Random(); int randomPos = random.nextInt(ServerIps.LIST.size()); return ServerIps.LIST.get(randomPos); } }
2、加权随机轮循算法
我们生产环境上部署多台服务,可能有的机器性能好,有的机器性能较差,我们希望更多的请求能够落在性能好的机器上,而性能差的机器处理更少的请求,这个时候我们就需要使用加权随机算法来实现负载均衡,可以通过Map来实现加权
public class ServerIps { public static final Map<String, Integer> WEIGHT_LIST = new HashMap<>(); static { WEIGHT_LIST.put("192.168.0.1",5); WEIGHT_LIST.put("192.168.0.2",3); WEIGHT_LIST.put("192.168.0.3",1); WEIGHT_LIST.put("192.168.0.4",6); WEIGHT_LIST.put("192.168.0.5",2); WEIGHT_LIST.put("192.168.0.6",1); WEIGHT_LIST.put("192.168.0.7",7); WEIGHT_LIST.put("192.168.0.8",1); WEIGHT_LIST.put("192.168.0.9",1); WEIGHT_LIST.put("192.168.0.10",1); } }
public class LoadBalance { public static String getServer(){ List<String> ips = new ArrayList<>(); ServerIps.WEIGHT_LIST.forEach((k, v) ->{ String ip = k; Integer weight = v; for (int i = 0;i < weight; i++){ ips.add(ip); } }); Random random = new Random(); int randomPos = random.nextInt(ips.size()); return ips.get(randomPos); } }
虽然上述代码可以实现加权随机的功能,但由于是通过在List中冗余的添加IP来实现的,会造成内存不必要的占用
改进版:
实现思想: 例如有三台机器权重分别为[5,2,3],随机值为offset=6
[- - - - - - 5 - - 2 - - - 3] 可以想象一份空间被分为三份,
判断 offset > 5 --> offset = offset - 5 --> offset = 1 结论:offset不在第一份空间
判断 offset < 2 结论:offset分布在第二份空间
public class LoadBalance {
public static String getServer(){
Integer totalWeight = 0;
for (Integer weight: ServerIps.WEIGHT_LIST.values()){
totalWeight += weight;
}
Random random = new Random();
int offset = random.nextInt(totalWeight);
for (Map.Entry<String,Integer> entry : ServerIps.WEIGHT_LIST.entrySet()){
String ip = entry.getKey();
Integer weight = entry.getValue();
if (offset < weight) {
return ip;
}
offset = offset - weight;
}
return "";
}
}