负载均衡-轮询算法

Posted 玩葫芦的卷心菜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了负载均衡-轮询算法相关的知识,希望对你有一定的参考价值。

轮询原理:

每次请求,请求数加1,然后对集群数取余,实现轮询数组
服务集合services,服务集群总数size=services.size();
当前接口请求cnt(每次请求cnt+1)
获取服务service.get(cnt%size)

如果服务集群有3个,
- 127.0.0.1:8001
- 127.0.0.1:8002
- 127.0.0.1:8003
第一次请求services[0%3=0] 127.0.0.1:8001
第二次services[1%3=1] 127.0.0.1:8002
第三次services[2%3=2] 127.0.0.1:8003
第四次services[3%3=0] 127.0.0.1:8001
第五次services[4%3=1] 127.0.0.1:8002
第六次services[5%3=2] 127.0.0.1:8003

注释掉RestTemplate的LoadBalanced注解,使用自定义的负载均衡

public interface LoadBalancer 
//    获取服务
    public ServiceInstance getInstance(List<ServiceInstance> instances);

@Component//注解注解,能够被扫描到
public class MyLB implements LoadBalancer 
//    原子整型初始0
    private AtomicInteger atomicInteger=new AtomicInteger(0);

    public final int getAndIncrement()
        int current;
        int next;
        do
            current=atomicInteger.get();//获取当前值
            next=current>=100?0:current+1;//请求数大于100从0开始,否则+1
        while(!atomicInteger.compareAndSet(current,next));//自旋锁CAS
        System.out.println("******next:"+next);
        return next;
    

    @Override
    public ServiceInstance getInstance(List<ServiceInstance> instances) 
        int index=getAndIncrement()%instances.size();//获取服务索引=下一个请求%集群总数
        return instances.get(index);//返回轮询获得的服务
    

利用CAS保证请求数的正确性
compareAndSet(current,next):current旧的预期值,next希望更新的值
将current与内存地址的值比较,如果相同,则替换成next,不同则失败

测试访问

@RestController
public class OrderController 

    public static final String PAYMENT_URL="http://CLOUD-PAYMENT-SERVICE";

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private LoadBalancer loadBalancer;

    @Resource
    private DiscoveryClient discoveryClient;
    
    @GetMapping("/consumer/payment/lb")
    public String nextLb()
   		 //获取所有CLOUD-PAYMENT-SERVICE服务
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        
        if(instances==null||instances.size()<=0)
            return null;
         //获取轮询请求的服务
        ServiceInstance instance = loadBalancer.getInstance(instances);
        URI uri=instance.getUri();
        System.out.println(uri);
        //调用该服务
        return restTemplate.getForObject(uri+"/payment/lb",String.class);
    


以上是关于负载均衡-轮询算法的主要内容,如果未能解决你的问题,请参考以下文章

负载均衡算法 — 轮询

工具系列 | 负载均衡算法 - 轮询算法

负载均衡之轮询算法

负载均衡之加权轮询算法(转)

Ribbon负载均衡算法

Nginx的负载均衡