Spring Cloud Ribbon原理

Ribbon是Netflix公司开源的一个负载均衡的项目,它属于上述的第二种,是一个客户端负载均衡器,运行在客户端上。Spring Cloud Ribbon是在Netflix Ribbon的基础上作了进一步的封装,使它更加适合与微服本文主要如下俩个方便分析Ribbon的原理算法

  1. Ribbon的和核心工做原理
  2. Ribbon的核心接口

1.Ribbon怎么和RestTemplate整合的

了解Spring boot的自动化装配的同窗都知道,在Spring boot启动过程当中会加载在/META-INF/spring.factories文件下定义的配置类,而和Ribbon相关的主要配置类为LoadBalancerAutoConfiguration,在以下文件下spring

 

 

查看LoadBalancerAutoConfiguration的源码可知,在其内部定义了一个LoadBalancerInterceptor的拦截器,用于实现对客户端发起请求时进行拦截,以实现客户端负载均衡。服务器

 

 

LoadBalancerInterceptor源码以下并发

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {

    private LoadBalancerClient loadBalancer;

    private LoadBalancerRequestFactory requestFactory;

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer,
            LoadBalancerRequestFactory requestFactory) {
        this.loadBalancer = loadBalancer;
        this.requestFactory = requestFactory;
    }

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
        // for backwards compatibility
        this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
    }

    @Override
    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
            final ClientHttpRequestExecution execution) throws IOException {
        final URI originalUri = request.getURI();
        String serviceName = originalUri.getHost();
        Assert.state(serviceName != null,
                "Request URI does not contain a valid hostname: " + originalUri);
        return this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
    }

}

从源码中能够看出,LoadBalancerInterceptor主要是将负载均衡的功能委托给负载均衡客户端LoadBalancerClient。负载均衡

在看一下RibbonLoadBalancerClient的excute方法dom

    public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
 ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);         Server server = this.getServer(loadBalancer, hint);
        if(server == null) {
            throw new IllegalStateException("No instances available for " + serviceId);
        } else {
            RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
            return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
        }
    }

从代码中能够看出LoadBalancerClient主要是经过负载均衡器ILoadBalancer查出对应的server而后执行。而getServer就是实现负载均衡的地方。ide

咱们再看一下getServer的实现函数

   protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
        return loadBalancer == null?null:loadBalancer.chooseServer(hint != null?hint:"default");
    }

发现是经过ILoadBalancer的chooseServer方法实现的,再看一下BaseLoadBalancer的chooseServer方法性能

public Server chooseServer(Object key) {
        if (counter == null) {
            counter = createCounter();
        }
        counter.increment();
        if (rule == null) {
            return null;
        } else {
            try {
                return rule.choose(key);
            } catch (Exception e) {
                logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", name, key, e);
                return null;
            }
        }
    }

咱们发现是经过rule.choose方法实现的,而rule实际上是IRule(负载均衡策略接口)。this

总结Ribbon的负载均衡实现,主要是经过LoadBalancerInterceptor拦截器在请求时进行拦截实现负载均衡,而LoadBalancerInterceptor将负载均衡委托给了LoadBalancerClient,而LoadBalancerClient具体交给了ILoadBalancer来处理,ILoadBalancer是根据IRule的策略进行负载均衡。

2.Ribbon的核心接口

Ribbon主要包括如下核心接口

接口 描述 默认实现
ILoadBalancer 负载均衡选择服务的核心方法接口 ZoneAwareLoadBalancer
IRule 负载均衡策略接口 ZoneAvoidanceRule
IPing 按期检查服务可用性的接口 DummyPing
ServerList<Server> 获取服务列表接口 ConfigurationBaseServerList
ServerListUpdate 更新服务列表接口 PollingServerListUpdate
ServerListFilter<Server> 过滤服务列表接口 ZonePerferenceServerListFilter
IClientConfig ribbon中管理配置接口 DefaultClientConfigImpl

 

 

 

 

 

 

 

 

下面咱们在介绍一下Ribbon的核心接口ILoadBalancer和IRule

2.1 ILoadBalancer 

ILoadBalancer的继承关系以下

 

 

 

ILoadBalancer:定义了负载均衡器的主要方法

AbstractLoadBalancer:实现 ILoadBalancer 接口,提供一些默认实现

BaseLoadBalancer:类是Ribbon负载均衡器的基础实现类,在该类中定义不少关于均衡负载器相关的基础内容

DynamicServerListLoadBalancer:它是对基础负载均衡器的扩展。在该负载均衡器中,实现了服务实例清单的在运行期的动态更新能力;同时,它还具有了对服务实例清单的过滤功能。

ZoneAwareLoadBalancer:负载均衡器是对DynamicServerListLoadBalancer的扩展。在DynamicServerListLoadBalancer中,咱们能够看到它并无重写选择具体服务实例的chooseServer函数,因此它依然会采用在BaseLoadBalancer中实现的算法,使用RoundRobinRule规则,以线性轮询的方式来选择调用的服务实例,该算法实现简单并无区域(Zone)的概念,因此它会把全部实例视为一个Zone下的节点来看待,这样就会周期性的产生跨区域(Zone)访问的状况,因为跨区域会产生更高的延迟,这些实例主要以防止区域性故障实现高可用为目的而不能做为常规访问的实例,因此在多区域部署的状况下会有必定的性能问题,而该负载均衡器则能够避免这样的问题。

2.2 IRule 负载均衡策略

ILoadBalancer是根据IRule定义的负载均衡策略来进行选择服务的,主要有如下7中负载均衡策略

Ribbon中的7中负载均衡算法:

RoundRobinRule:轮询;

RandomRule:随机;

AvailabilityFilteringRule:会先过滤掉因为屡次访问故障而处于断路器状态的服务,还有并发的链接数量超过阈值的服务,而后对剩余的服务列表按照轮询策略进行访问;

WeightedResponseTimeRule:根据平均响应时间计算全部服务的权重,响应时间越快的服务权重越大被选中的几率越大。刚启动时若是统计信息不足,则使用RoundRobinRule(轮询)策略,等统计信息足够,会切换到WeightedResponseTimeRule;

RetryRule:先按照RoundRobinRule(轮询)策略获取服务,若是获取服务失败则在指定时间内进行重试,获取可用的服务;

BestAvailableRule:会先过滤掉因为屡次访问故障而处于断路器跳闸状态的服务,而后选择一个并发量最小的服务;

ZoneAvoidanceRule:复合判断Server所在区域的性能和Server的可用性选择服务器;

相关文章
相关标签/搜索