前言
本篇实现一下分布式中负载均衡的实现策略,以及负载均衡算法是如何实现的。
什么是负载均衡?
Java负载均衡是指在多台服务器之间分配负载,以提高服务器的性能和可用性。它通过将请求分发到多台服务器来减少单个服务器的压力,从而提高系统的性能和可用性。
算法实现
举个例子:在hcr-user服务中,存在三条集群实例。
每次请求都要请求不同的服务,那么就需要有一个全局的计数器来进行计数。
AtomicInteger是concurrent包下的一个原子类。
public class MyTest {
private AtomicInteger count = new AtomicInteger(0);
@Test
public void test() {
List<String> list = new LinkedList<>();
list.add("服务A");
list.add("服务B");
list.add("服务C");
//让原子计数器+1并 % 当前服务集合长度 = 当前请求执行集群的实例
//返回实例下标
int index = count.incrementAndGet() % list.size();
//根据集合下标找到当前集群的实例
String service = list.get(index);
System.err.println(service);
}
}
代码实现
1轮询
@Component
public class RoundLoadBalance implements LoadBalance {
@Resource
private DiscoveryClient client;
//创建一个原子类的计数器
private AtomicInteger atomicCount = new AtomicInteger(0);
/**
* 使用轮询的方式完成负载均衡算法实现
*
* @param serviceId 服务id
* @return {@link ServiceInstance}
*/
public ServiceInstance getInstances(String serviceId) {
//获取到服务的集合(集群)
List<ServiceInstance> list = client.getInstances(serviceId);
if (list != null && list.size() > 0) {
//将当前原子计数器 + 1(incrementAndGet方法相当于i++)% 服务集合的长度 = 本次调用服务
int index = atomicCount.incrementAndGet() % list.size();
return list.get(index);
}
return null;
}
}
2随机
@Component
public class RandomLoadBalance implements LoadBalance {
@Resource
private DiscoveryClient client;
/**
* 实现随机算法完成负载均衡
*
* @param serviceId 服务id
* @return {@link ServiceInstance}
*/
public ServiceInstance getInstances(String serviceId) {
List<ServiceInstance> list = client.getInstances(serviceId);
if (list != null && list.size() > 0) {
Random random = new Random();
//随机数值范围:0-集合长度,例如集合为3,那么值的范围就是 0 1 2
int index = random.nextInt(list.size());
return list.get(index);
}
return null;
}
}
3权重
@Component
public class WeightLoadBalance implements LoadBalance {
@Resource
private DiscoveryClient client;
private AtomicInteger atomicCount = new AtomicInteger(0);
/**
* 使用权重算法实现负载均衡
*
* @param serviceId 服务id
* @return {@link ServiceInstance}
*/
public ServiceInstance getInstances(String serviceId) {
//通过服务名称获取到服务集群实例
List<ServiceInstance> list = client.getInstances(serviceId);
if (list != null && list.size() > 0) {
List<ServiceInstance> total = new LinkedList<ServiceInstance>();
for (ServiceInstance instance : list) {
//获取到nacos中服务配置的权重
Double weight = Double.parseDouble(instance.getMetadata().get("nacos.weight"));
for (int i = 0; i < weight; i++) {
//对权重的大小进行循环比对,将服务实例添加到新的集合中。
//权重越小,循环越少,集合中该服务就越少
//权重越大,循环越多,集合中该服务就越多
total.add(instance);
}
}
//将新的集合与计数器进行计算,获取到服务下标
int index = atomicCount.incrementAndGet() % total.size();
return total.get(index);
}
return null;
}
}
总结
这篇只是了解一下负载均衡的算法是如何实现的,在平常使用的话,feign里已经实现了负载均衡策略,所以不需要我们手动去撸代码实现。