一、Ribbon有哪些自带的负载均衡算法
默认出厂设置用的是轮询算法,就是每个服务列表按顺序依次访问;
二、怎么替换默认的负载均衡算法
首先注意一点,算法配置文件不能处于@ComponentScan注解所在的包及其子包下,原因就不说了,自己百度去。
所以第一步,新建一个包com.xiexiaoyu.ribbon,然后新建一个配置类
@Configuration
public class MySelfRule
{
@Bean
public IRule myRule()
{
return new RandomRule();//定义为随机
}
}
然后在主启动类上加入注解
//访问CLOUD-PAYMENT-SERVICE服务时采用MySelfRule类中定义的负载均衡算法
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration=MySelfRule.class)
over,这样就把这个客户 端的负载均衡算法换成了随机访问算法
三、手写负载均衡算法
1、ApplicationContextBean去掉注解@LoadBalance
ApplicationContextConfig用于返回一个RestTemplate实例,用于rest接口调用。
@Configuration
public class ApplicationContextConfig
{
@Bean
//@LoadBalanced
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
}
2、手写一个LoadBalance接口
1)LoadBalancer接口声明返回从一组微服务中返回其中一个
public interface LoadBalancer
{
ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
2)MyLB实现类实现LoadBalancer接口
@Component
public class MyLB implements LoadBalancer
{
private AtomicInteger atomicInteger = new AtomicInteger(0);
public final int getAndIncrement()
{
int current;
int next;
//自旋锁确定微服务索引
do {
current = this.atomicInteger.get();
next = current >= 2147483647 ? 0 : current + 1;
}while(!this.atomicInteger.compareAndSet(current,next));
System.out.println("*****第几次访问,次数next: "+next);
return next;
}
//负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标 ,每次服务重启动后rest接口计数从1开始。
@Override
public ServiceInstance instances(List<ServiceInstance> serviceInstances)
{
int index = getAndIncrement() % serviceInstances.size();
return serviceInstances.get(index);
}
}
3)Controller层调用负载均衡算法
微服务8001,注册成CLOUD-PAYMENT-SERVICE:
@RestController
@Slf4j
public class PaymentController
{
//server.port=8001 写在配置文件的,这里不单独列出了,不是本文重点
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/payment/lb")
public String getPaymentLB()
{
return serverPort;
}
}
微服务8002,注册成CLOUD-PAYMENT-SERVICE:
@RestController
@Slf4j
public class PaymentController
{
//server.port=8002 写在配置文件的,这里不单独列出了,不是本文重点
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/payment/lb")
public String getPaymentLB()
{
return serverPort;
}
}
服务消费者:
@RestController
@Slf4j
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(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 = loadBalancer.instances(instances);
URI uri = serviceInstance.getUri();
return restTemplate.getForObject(uri+"/payment/lb",String.class);
}
}
完活!有兴趣的可以自己实现IRule接口,然后配置负载均衡实现类为自己定义的IRule实现类