Ribbon中的内置的负载均衡算法,都实现了IRule接口。因此如果我们要自定时负载均衡算法也要实现IRule接口。
Ribbon中已经实现了IRule接口的类:这些类都是Ribbon中的负载均衡算法,抽象类除外。
IRule接口中有两个类型值得注意:Server和ILoadBalancer。Server封装了是注册进Eureka的微服务信息,也就代表注册进Eureka的微服务。而ILoadBalancer是一个接口,用来获取注册进Eureka的全部或部分或某个微服务信息,如下:
public interface ILoadBalancer { void addServers(List<Server> var1); Server chooseServer(Object var1); void markServerDown(Server var1); /** @deprecated */ @Deprecated List<Server> getServerList(boolean var1); List<Server> getReachableServers(); List<Server> getAllServers(); }到这里可以看出,IRule接口是通过ILoadBalancer来获取Server,进而实现负载均衡。下面我们以RandomRule为例分析IRule如何实现负载均衡,以及我们如何自定义实现负载均衡.
RandomRule继承了AbstractLoadBalancerRule 抽象类,而AbstractLoadBalancerRule 实现了IRule:
AbstractLoadBalancerRule :
public abstract class AbstractLoadBalancerRule implements IRule, IClientConfigAware { private ILoadBalancer lb; public AbstractLoadBalancerRule() { } public void setLoadBalancer(ILoadBalancer lb) { this.lb = lb; } public ILoadBalancer getLoadBalancer() { return this.lb; } }综上可以看出,RandomRule继承AbstractLoadBalancerRule重写IRule接口的choose方法,实现负载均衡。那么我们自定义负载均衡算法,只需要仿照RandomRule,继承AbstractLoadBalancerRule,重写 choose(Object key)方法,自定义实现负载均衡规则。
MyIRule:
public class MyIRule extends AbstractLoadBalancerRule { Random rand = new Random(); public RandomRule() { } @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"}) public Server choose(ILoadBalancer lb, Object key) { ...... ...... } public Server choose(Object key) { return this.choose(this.getLoadBalancer(), key); } public void initWithNiwsConfig(IClientConfig clientConfig) { } }使自定义负载均衡算法起作用,不能像使用Ribbon中默认负载均衡算法一样直接注入容器,需要注意以下几点:
自定义的负载均衡算法,不能在SpringBoot启动时扫描到,即自定义的负载均衡类,不能放在启动类的子包或启动类所在包中。定义配置类将自定义的负载均衡算法注入Spring容器中。(配置类也不能被启动类扫描到)启动类上添加注解@RibbonClient(name="微服务名", configuration="装载自定义负载均衡算法的配置类")。 @SpringBootApplication @EnableEurekaClient //在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效 @RibbonClient(name="cloud-provider",configuration=MySelfRuleConfig.class) public class CloudRibbon{ public static void main(String[] args) { SpringApplication.run(CloudRibbon.class, args); } }
