1.在服务的消费方提供一个接口
public interface LoadBalancer{
// serviceInstanceList 为eureka中服务的数量
ServiceInstance instance(List<ServiceInstance> serviceInstanceList);
}
2.实现接口
@Component // 注意一定要将其注入到spring容器之中
public class MyLb implements LoadBalancer{
// 原子类,保证多线程安全,赋予初始化值为0
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));
// CAS 和内存的数据比较,没有更改,则改为期望的值
return next;
}
@Override
public ServiceInstance instance(List<ServiceInstance> serviceInstanceList) {
// 算法: 实际调用服务器位置下标 = rest 接口第几次请求数 % 服务器集群总个数
int index = getAndIncrement() % serviceInstanceList.size();
return serviceInstanceList.get(index);
}
}
3.Controller接口实现 ,记住注释@LoadBalanced
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
@Resource
private DiscoveryClient discoveryClient;
@Resource
private LoadBalancer loadBalanced;
@GetMapping(value = "/consumer/payment/lb")
public String getPaymentLB(){
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if(instances == null || instances.size()<=0){
return null;
}
ServiceInstance serviceInstance = loadBalanced.instance(instances);
URI uri = serviceInstance.getUri();
return restTemplate.getForObject(uri+"/payment/lb",String.class);
}