SpringCloud篇之手写轮询算法(Ribbon轮询算法)
程序员文章站
2022-05-29 13:04:38
...
本片主要介绍SpringCloud中基于netflix 的Ribbon负载均衡中的轮询机制。
Ribbon不同于Nginx,Ribbon是本地负载均衡,而Nginx是客户端负载均衡,作用点不同。Ribbon主要是对服务接口调用的一种负载机制。在Ribbon中,以IRule作为负载策略。其中默认的是轮询机制,本篇即模仿Ribbon手写一个轮询算法。
先来看看IRule的继承关系
其中的RoundRobinRule就是轮询策略
下面我们开始手写一个轮询策略
首先事先做好我们的基本环境,这里使用的是Eureka作为服务与发现注册中心
服务注册中心
服务提供者
为了达到负载测试的效果,这里需要提供两个服务提供者
服务消费者
搭建好基本的机构之后我们开始编写我们的轮询算法
1、创建核心接口--用于调用目标服务
/**
* 轮询接口
*/
public interface LoadBalance {
ServiceInstance getInstance(List<ServiceInstance> serviceInstances);
}
2、创建接口实现类--编写核心算法
@Component
public class MyLoadBalancer implements LoadBalance {
//原子封装类
private AtomicInteger atomicInteger = new AtomicInteger(0);
/**
* 计算得到当前调用次数
* @return
*/
public final int getAndIncrement(){
int current;
int next;
do {
current = atomicInteger.get();
next = current >= Integer.MAX_VALUE ? 0 : current+1;
}while (!atomicInteger.compareAndSet(current,next)); //利用CAS保证原子操作
return next;
}
/**
* 轮询算法
* 当前调用数 % 服务实例数量
* @param serviceInstances
* @return
*/
@Override
public ServiceInstance getInstance(List<ServiceInstance> serviceInstances) {
int index = this.getAndIncrement() % serviceInstances.size();
//根据下标返回对应的服务实例
return serviceInstances.get(index);
}
}
3、策略调用
@RestController
@Slf4j
public class OrderController {
@Resource
private RestTemplate restTemplate;
@Resource
private MyLoadBalancer myLoadBalancer;
@Resource
private DiscoveryClient discoveryClient;
@GetMapping(value = "/consumer/payment/getInstance/{id}")
public GeneralResult<Integer> getPaymentByInstance(@PathVariable("id")Long id){
//获取所有服务实例
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if(instances == null || instances.size() <= 0){
return null;
}
//根据我们的轮询算法得到对应的服务实例
ServiceInstance instance = myLoadBalancer.getInstance(instances);
//根据服务实例获得服务器的uri
URI uri = instance.getUri();
return restTemplate.getForObject(uri+"cloud/payment/get/"+id,GeneralResult.class);
}
}
至此我们的服务轮询机制已经完成
最后我们可以看到每一次请求都循环更换端口
上一篇: 吃顿火锅,万事大吉