所有代码都在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<ServiceInstance> 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<ServiceInstance> 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<ServiceInstance> 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、查看测试结果,验证接口返回的端口号 实现了轮询功能