Spring-Cloud之Ribbon原理剖析

2021年11月20日 阅读数:2
这篇文章主要向大家介绍Spring-Cloud之Ribbon原理剖析,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

咱们知道Ribbon主要的工做就是进行负载均衡,帮助咱们无需再关注微服务中集群的地址信息,所以在源码剖析中咱们就主要关注这部分的内容。java

内置的负载均衡规则

  • RoundRobinRule:直接轮询的方案;即每次从server list中依次选择。
  • AvailabilityfileringRule:根据服务器可用性来决定;好比某个服务器的并发请求太高,那么此时ribbon就会绕过再也不访问;同时若是3次链接失败就会等待30秒后再次访问;若是不断失败,那么等待时间会不断变长,若是某个服务器的并发请求过高了,那么会绕过去,再也不访问。
  • WeightedResponseTimeRule:根据权重来分配;每一个服务器均可以有权重,权重高就优先访问,若是某个服务器响应时间比较长,那么权重就会下降,减小访问。
  • ZoneAvoidanceRule:根据区域和服务器来进行负载均衡,也就是根据机房来分配,里面再使用轮询的方式。默认的就是这个
  • BestAvailableRule:忽略链接失败的服务器,同时尽可能找并发比较低的服务器来请求。
  • RandomRule:随机选择一个。
  • RetryRule:在轮询的方案上增长重试机制;即经过轮询的方式选择一个服务器请求,在失败的时候会从新再找一个重试。

能够经过ribbon.NFLoadBalancerRuleClassName: top.vchar.MyRule 来切换规则缓存

RestTemplate 加上 @LoadBalanced

当咱们在 RestTemplate 上添加 @LoadBalanced 注解后,在写接口地址的时候能够直接使用服务名代替真实的地址;在执行请求的过程当中Ribbon会自动的将其替换为真实的地址。 加上 @LoadBalanced 注解就可让 RestTemplate的请求交ribbon的原理以下:服务器

  • 在ribbon的整合中有个LoadBalancerAutoConfiguration的配置,它里面会注入全部带@LoadBalanced 注解的 RestTemplate的bean;而后会给这些RestTemplate添加上一个LoadBalancerInterceptor的拦截器;
  • 在 RestTemplate 执行请求的时候,这个拦截器会拦截请求,将其转给LoadBalancerClient(实际是RibbonLoadBalancerClient来实现的)来作接下来的所有操做。
  • 在RibbonLoadBalancerClient中会根据服务名从注册表获取该服务对应的服务信息集合,而后根据设置的负载均衡规则选择一个服务信息;
  • 以后将将请求地址中的服务名称称替换为真实的地址,而后发起请求。

IPing机制

Ribbon中IPing机制其实就是定时的去检查拿到的注册表中的服务是否可用,若是不可用将会移除它。默认使用NIWSDiscoveryPing类实现IPing;它就是启动了一个定时任务,默认每隔30s执行一次,经过检查服务的状态是不是UP状态来判断该服务是否存活。并发

public boolean isAlive(Server server) {
    boolean isAlive = true;
    if (server != null && server instanceof DiscoveryEnabledServer) {
        DiscoveryEnabledServer dServer = (DiscoveryEnabledServer)server;
        InstanceInfo instanceInfo = dServer.getInstanceInfo();
        if (instanceInfo != null) {
             InstanceStatus status = instanceInfo.getStatus();
             if (status != null) {
                 isAlive = status.equals(InstanceStatus.UP);
             }
        }
    }
    return isAlive;
}

关于Ribbon获取服务注册表

Ribbon并无直接使用eureka client的注册表信息,而是拷贝了一份注册表信息从新封装了一下。 它在初始化的时候会经过PollingServerListUpdater来启动一个定时任务,默认每隔30s到eureka client的注册表中拷贝一次而后刷新它本身的。这个时间能够经过配置 ribbon.ServerListRefreshInterval 来修改定时任务的执行间隔时间。负载均衡

那么若是某台机器故障宕机,ribbon须要多久才能感知到呢?下面咱们来分析下:首先eureka server的服务故障感知最坏的状况下是须要180s,同时只读缓存默认30s才会自动更新,eureka client默认30s才会去拉取一次注册信息,加上ribbon本身的刷新时间30s,那么整个过程须要的时间就是180s+30s+30s+30s=270s,也就是大约要4分钟半左右。dom

关于Ribbon的配置

Ribbon配置支持的key在ribbon-core中的CommonClientConfigKey类中,咱们能够根据须要到里面去查阅;配置方式分为全局和局部。微服务

  • 所有配置直接以ribbon开头,好比:ribbon.ServerListRefreshInterval:20 修改ribbon刷新注册表的时间
  • 局部配置就是针对某个服务的配置,格式为:<clientName>.<nameSpace>.<propertyName>=<value> ;示例
# 配置memberServer的服务调用失败的时候重试一次
memberServer.ribbon.MaxAutoRetries=1