067:手写RPC负载均衡器五种算法
1 手写RPC负载均衡器五种算法演示
课程内容:
1.负载均衡器在RPC调用中实现的作用
2.五种RPC框架负载均衡器的种类
3.基于策略模式设计负载均衡器
4.手写五种负载均衡器算法
2 负载均衡器在RPC框架实现的作用
Rpc是远程调用技术 dubbo、feign、httpclient
任何rpc框架都必须有本地负载均衡器eg:ribbon,dubbo自带负载均衡器
负载均衡器在rpc中作用?
能够提高生产者服务器集群访问,分摊压力。
原理:从一个集合列表地址元素中,采用负载均衡器算法最终获取一个地址实现调用。
负载均衡算法:轮询、权重、一致性hash、随机权重、随机
3 手写负载均衡器轮询机制第一种算法
public interface LoadBalancer<T> {
// 从一个集群地址中获取单个rpc调用地址
String getAddress(List<T> address);
}
public class RotationLoadBalancer implements LoadBalancer<String> {
private int index;
public synchronized String getAddress(List<String> address) {
if (index >= address.size()) {
// 重置为0
index = 0;
}
String value = address.get(index++);
System.out.println("value:" + value);
return value;
}
}
public class Test001 {
public static void main(String[] args) {
LoadBalancer loadBalancer = new RotationLoadBalancer();
ArrayList<String> strings = new ArrayList<String>();
strings.add("127.0.0.1:8080");
strings.add("127.0.0.1:8081");
loadBalancer.getAddress(strings);
loadBalancer.getAddress(strings);
loadBalancer.getAddress(strings);
loadBalancer.getAddress(strings);
}
}
运行结果:
4 手写负载均衡器轮询机制第二种算法
public class RotationLoadBalancer2 implements LoadBalancer<String> {
// 原子类计数器,从0开始计数
private AtomicInteger atomicInteger = new AtomicInteger(0);
public String getAddress(List<String> address) {
String value = address.get(atomicInteger.incrementAndGet() % address.size());
System.out.println("value:" + value);
return value;
}
}
public class Test002 {
public static void main(String[] args) {
LoadBalancer loadBalancer = new RotationLoadBalancer2();
ArrayList<String> strings = new ArrayList<String>();
strings.add("127.0.0.1:8080");
strings.add("127.0.0.1:8081");
loadBalancer.getAddress(strings);
loadBalancer.getAddress(strings);
loadBalancer.getAddress(strings);
loadBalancer.getAddress(strings);
}
}
运行结果:
轮询机制算法两种写法:
- 使用index实现自增,注意判断index不要越界
- 访问的次数 % 列表长度
5 手写负载均衡器权重设计算法
权重算法原理就是根据权重的大小实现排序,重新生成一个新的集合。
权重轮询
127.0.0.1:8080 weight 1
127.0.0.1:8081 weight 2
address[0]= 127.0.0.1:8080
address[1]= 127.0.0.1:8081
address[2]= 127.0.0.1:8081
@Data
@AllArgsConstructor
public class WeightEntity {
/**
* 地址
*/
private String address;
/**
* 权重大小
*/
private int weight;
}
public class WeightLoadBalancerUtils {
// 对集合权重实现排序
public static List<String> weightToRotation(List<WeightEntity> listWeight) {
ArrayList<String> listAddress = new ArrayList<String>();
for (int i = 0; i < listWeight.size(); i++) {
// 获取配置的权重大小
WeightEntity weightEntity = listWeight.get(i);
for (int j = 0; j < weightEntity.getWeight(); j++) {
listAddress.add(listWeight.get(i).getAddress());
}
}
return listAddress;
}
}
public class WeightLoadBalancer implements LoadBalancer<WeightEntity> {
private int index;
public synchronized String getAddress(List<WeightEntity> addresss) {
List<String> strings = WeightLoadBalancerUtils.weightToRotation(addresss);
if (index >= strings.size()) {
// 重置为0
index = 0;
}
String value = strings.get(index++);
System.out.println("value:" + value);
return value;
}
}
public class Test003 {
public static void main(String[] args) {
ArrayList<WeightEntity> weightEntities = new ArrayList<WeightEntity>();
weightEntities.add(new WeightEntity("127.0.0.1:8080",1));
weightEntities.add(new WeightEntity("127.0.0.1:8081",2));
WeightLoadBalancer loadBalancer = new WeightLoadBalancer();
loadBalancer.getAddress(weightEntities);
loadBalancer.getAddress(weightEntities);
loadBalancer.getAddress(weightEntities);
loadBalancer.getAddress(weightEntities);
loadBalancer.getAddress(weightEntities);
loadBalancer.getAddress(weightEntities);
}
}
运行结果:
6 手写负载均衡器一致性hash算法
一致性hash用户ip绑定 相同ip获得地址不变
public class IpHashLoadBalancer {
public String getAddress(List<String> address, String ipAddr) {
String vaule = address.get(ipAddr.hashCode() % address.size());
System.out.println("value:" + vaule);
return vaule;
}
}
public class Test004 {
public static void main(String[] args) {
IpHashLoadBalancer ipHashLoadBalancer = new IpHashLoadBalancer();
ArrayList<String> strings = new ArrayList<String>();
strings.add("127.0.0.1:8080");
strings.add("127.0.0.1:8081");
ipHashLoadBalancer.getAddress(strings,"192.168.0.1");
ipHashLoadBalancer.getAddress(strings,"192.168.0.1");
ipHashLoadBalancer.getAddress(strings,"192.168.0.2");
ipHashLoadBalancer.getAddress(strings,"192.168.0.2");
}
}
运行结果: