Ribbon之自定义负载均衡算法实现

所有代码都在github上:https://github.com/demonruin/cloud2020/tree/master

 

负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下表,每次服务重启后rest接口计数从1开始

1、先去掉ApplicationContextConfig的@LoadBalance注解,即restTemplate上的注解,防止影响测试结果

package com.king.springcloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * created by king on 2020/4/13 3:54 下午
 */
@Configuration
public class ApplicationContextConfig {
    @Bean
    //@LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

2、先建立一个接口MyLoadBalancer,能通过服务器集合获取服务器的接口

package com.king.springcloud.lb;

import org.springframework.cloud.client.ServiceInstance;

import java.util.List;

/**
 * created by king on 2020/4/15 2:15 下午
 */
public interface MyLoadBalancer {
    //收集服务器总共有多少台能够提供服务的机器,并放到list里面
    ServiceInstance instance(List serviceInstances);
}

3、写自己的负载均衡算法MyLb类,要注意加注解 @Component,定义原子类,使用cas的自旋锁

package com.king.springcloud.lb;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * created by king on 2020/4/15 2:19 下午
 * 为了防止restTemplate中的@loadbalance注解影响,所以自定义负载均衡算法的时候,会将那个注解注释掉
 * 此为自定义LoadBalancer
 */
@Component
public class MyLb implements MyLoadBalancer {
    //定义原子类
    private AtomicInteger atomicInteger = new AtomicInteger(0);

    //通过自旋锁,cas,得到第几次访问次数
    private final int getAndIncrement() {
        int current;
        int next;
        do {
            current = this.atomicInteger.get();
            next = current > Integer.MAX_VALUE ? 0 : current + 1;
        } while (!this.atomicInteger.compareAndSet(current, next));
        System.out.println("***第几次访问,访问次数:"+next);
        return next;
    }

    //负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下表,每次服务重启后rest接口计数从1开始
    public ServiceInstance instance(List serviceInstances) {
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}

4、写测试controller类,来查看结果端口是否实现了轮训功能

package com.king.springcloud.controller;

import com.king.springcloud.lb.MyLoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.net.URI;
import java.util.List;

/**
 * created by king on 2020/4/15 2:34 下午
 */
@RestController
@Slf4j
public class LbController {
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private MyLoadBalancer loadBalancer;

    @Resource
    private DiscoveryClient discoveryClient;

    @GetMapping(value="/consumer/getLb")
    public String getLb(){
        List instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        if(instances==null || instances.size()==0){
            return null;
        }
        ServiceInstance instance = loadBalancer.instance(instances);
        URI uri = instance.getUri();
        return restTemplate.getForObject(uri+"/payment/lb/",String.class);
    }
}

此时在另微服务提供者中添加测试接口

package com.king.springcloud.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;

/**
 * created by king on 2020/4/13 2:48 下午
 */
@RestController
@Slf4j
public class PaymentController {

    @Value("${server.port}")
    private String serverPort;

    @GetMapping(value = "/payment/lb")
    public Object lb() {
        return serverPort;
    }

}

5、查看测试结果,验证接口返回的端口号 实现了轮询功能Ribbon之自定义负载均衡算法实现_第1张图片

 

你可能感兴趣的:(SpringCloud,Ribbon,负载均衡,自定义负载均衡,负载均衡算法,LoadBalance)