算法简单分析
负载均衡可以放在客户端,也可以放在服务端; 考虑每种算法的适用性有很多种角度, 比如机器处理能力,可扩展性,系统稳定性,业务定制化服务等,简单罗列算法的优缺点,个人理解;
1. 随机算法
机器配置相同,处理能力相似,但是dubbo默认的是随机算法;
2. 轮询算法
机器配置相同,处理能力差不多;
3. 最小活跃数
缺点: 服务能力弱的机器会吃不消,在服务能力偏弱的情况下,会强制跟服务能力强的机器靠近匹配(cpu密集型和io密集型);
优点: 机器性能好,处理的数据就越多,积压请求少, 而且相对保证集群稳定;
4. 一致性hash
适合集群服务节点的增加和减少;
5. 加权方法
针对服务器服务能力不一样,差异化对待处理;
6. hash方法
hash映射是固定的,那服务请求也会固定映射到指定服务器;
以上方法,随机和轮询需要考虑差异, 随机可用性会更高,系统服务异常调用次数会低点;
LVS&Nginx&HAProxy
LVS: 工作在网络层,
加权轮询,加权随机 比较好的方法:
加权轮询有一种是把所有机器ip放到List里面,这种对于机器比较多的情况下不是很友好;
/**
* 加权轮询
* @param num
* @return
*/
public static String getServer(int num) {
int totalWeight = SERVER_MAP.values().stream().mapToInt(x -> x).sum();
int server = num % totalWeight;
for (String serverName : SERVER_MAP.keySet()) {
int serverWeight = SERVER_MAP.get(serverName);
if(server < serverWeight ) {
return serverName;
}
server = server - serverWeight;
}
return "";
}
平滑加权随机:
public static String getSmoothServer() {
if(SERVER_WEIGHT_MAP.isEmpty()) {
SERVER_MAP.forEach((key, value) -> {
SERVER_WEIGHT_MAP.put(key, new Weight(key, 0, value));
});
}
int totalWeight = SERVER_WEIGHT_MAP.values().stream().mapToInt(x -> x.getWeight()).sum();
SERVER_WEIGHT_MAP.forEach((key, weight)-> {
weight.setCurrWeight(weight.getCurrWeight() + weight.getWeight());
});
Weight maxWeight = null;
for(Weight item : SERVER_WEIGHT_MAP.values()) {
if(null == maxWeight || maxWeight.getCurrWeight() < item.getCurrWeight()) {
maxWeight = item;
}
}
maxWeight.setCurrWeight(maxWeight.getCurrWeight() - totalWeight);
printWeight(SERVER_WEIGHT_MAP);
return maxWeight.getServiceName();
}