首先了解一下负载均衡。
百度百科:
负载均衡,英文名称为Load Balance,其含义就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,例如FTP服务器、Web服务器、企业核心应用服务器和其它主要任务服务器等,从而协同完成工作任务。
个人理解,负载均衡,顾名思义,就是让硬件或服务,所受的负载,尽量均衡一点。
物尽其用,如250G固态硬盘和1T机械硬盘。
作为系统盘,则选择用250G的固态,读取和写入的速度块。
有很多学习资源要存,容量较大,那么就会1T的机械硬盘。
择优选择,打疫苗时,A,B,C三个医院,A医院爆满,C医院人数较少,那么就去C医院。
Dubbo四种负载均衡
①:随机权重(Random LoadBalance)。(dubbo默认)
A:权重40 占比2/5
B:权重20 占比1/5
C:权重40 占比2/5
则每次请求,都是随机访问的,可能A,可能B,可能C。数据量大的情况下,就会形成权重的比例。
②:轮询(RoundRobin LoadBalance)
轮循,按公约后的权重设置轮循比率。(可以根据权重轮询,如2/5,1/5,2/5。5个请求,则 A-B-C-A-C)无权重则A-B-C-A-B-C....
存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
③:最少活跃调用数(LeastActive LoadBalance)
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
A:200ms
B:200ms
C:300ms
先看一下上次调用时间,请求优先调用A和B,随机选择。统计上一次的调用时间
④:一致性hash(ConsistentHash LoadBalance)
一致性 Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
缺省只对第一个参数 Hash,如果要修改,请配置 <dubbo:parameter key="hash.arguments" value="0,1" />
缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key="hash.nodes" value="320" />
方法名,和第一个参数名,getUser?id=1,调用服务A,则下次同方法同参数,会继续调用服务A,除非服务A挂掉,那么就会根据虚拟节点,平摊给其他服务提供者。算法处理。
个人理解的权重算法
/**
* <h3>根据权重获取对应服务,传入服务:权重map</h3>
*
* @param map 服务:权重map
* @return java.lang.String
* @author Hubers
* @date 2021/6/15 16:16
**/
public static String getServerByWeight(Map<String, Integer> map) {
if (map.isEmpty()){
return null;
}
Integer total = 0;
// 计算所有权重,如100+200+300=600
for (Integer value : map.values()) {
total += value;
}
Random random = new Random();
// 在权重范围内随机,600以内随机
int nextInt = random.nextInt(total);
// 遍历所有服务提供者provide的ip地址
for (String ip : map.keySet()) {
// 取出权重值
Integer weight = map.get(ip);
// 权重在范围内,则返回对应ip
if (nextInt < weight) {
return ip;
}
// 否则减去权重,继续下一次循环,匹配对应的ip
nextInt -= weight;
}
return null;
}
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("192.168.1.1", 10);
map.put("192.168.1.2", 10);
map.put("192.168.1.3", 10);
map.put("192.168.1.4", 10);
for (int i = 0; i < 10; i++) {
String weight = getServerByWeight(map);
if (Objects.isNull(weight)) {
throw new RuntimeException("无可用服务");
}
System.out.println(weight);
}
}