springcloud之ribbon

时间秒杀一切 提交于 2019-12-13 08:45:24

springcloud之ribbon

  • 概念也就是说在自动装配里面利用拦截器来做到负载均衡
    • @ConditionalOnClass(RestTemplate.class): RestTemplate 类必须存在于当前工程的环境中。
    • @ConditionalOnBean(LoadBalancerClient.class): 在Spring 的Bean工程中必须有LoadBalancerClient的实现 Bean。

  • 在该自动化配置类中, 主要做了下面三件事:
    • 创建了 一 个LoadBalancerInterceptor的Bean, 用千实现对客户端发起请求时进行拦截, 以实现客户端负载均衡。
    • 创建了一 个RestTemplateCustomizer的Bean,用于给RestTemplate增加LoadBalancerInterceptor拦截器。
    • 维护了一 个被@LoadBalanced 注解修饰的RestTempllate对象列表,并在这里进行初始化, 通过调用RestTemplateCustomizer的实例来给需要客户端负载均衡的RestTemplate增加LoadBalancerinIerceptor拦截器。

  • 流程:通过 LoadBalancerinterceptor拦截器对 RestTemplate的请求进行拦截, 并利用Spring Cloud的负载均衡器 LoadBalancerClient将以逻辑服务名为host的 URI转换成具体的服务实例地址的过程.同 时 通 过分析LoadBalancerClient 的Ribbon实现rebbonLoadBalancerClient, 可以知道在使用rebbon实现负载均衡器的时候,实际使用的还是Ribbon中定义的ILoadBalancer接口的实现,自动化配置会采用ZoneAwareLoadBalancer的实例来实现客户端负载均衡

负载均衡策略

  • RandomRule:随机,:通过负载均衡器和key来选择,具体的选择逻辑在 一 个 while(server == null) 循环之内, 而根据选择逻辑的实现,正常情况下每次选择都应该选出一个服务实例, 如果出现死循环获取不到服务实例时,则很有可能存在并发的 Bug

  • RoundRobinRule:线性轮询,从可用列表中获取所谓的逻辑。从循环条件中,我们可以看到增加了
    一 个count计数变量, 该变量会在每次循环之后累加, 也就是说, 如果 一 直选择不到 server 超过 10 次, 那么就会结束尝试, 并打印 一 个警告信息 No available alive servers after 10 tries from load balancer

  • RetryRule:具备重试机制的实例选择器,默认是使用RoundRobinRule的实例,在 choose 方法中则实现了对内部定义的策略进行反复尝试的策略, 若期间能够选择到具体的服务实例就返回,若选择不到就根据设置的尝试结束时间为阈值 CmaxRetryMillis 参数定义的值+ choose 方法开始执行的时间戳), 当超过该阑值后就返回 null

  • WeightedResponseTimeRule:该策略是对 RoundRobinRule 的扩展, 增加了根据实例的运行情况来计算权重, 并根据权重来挑选实例, 以达到更优的分配效果逐个计算每个实例的权重:weightSoFar + totalResponseTime -实例的平均响应时间
    该函数的实现主要分为两个步骤:

    • 根据LoadBalancerStats中记录的每个实例的统计信息, 累加所有 实例的平均响应时间, 得到总平均响应时间七otalResponseTime, 该值会用于后续的计算。
    • 为负载均衡器中维护的实例清单逐个计算权重(从第一个开始), 计算规则为weightSoFar+totalResponseTime - 实例的平均响应时间,其中weightSoFar初始化为零, 并且每 计算好 一 个权重需要累加到weightSoFar上供下一 次计算使用
    • 并不是平均响应时长最短就一定会被选上,只是说概率更大,他们形成的值会组成一个区间,然后 区间的宽度越宽,被选中的概率就越大
  • 选择的步骤

    • 生成 一 个[0, 最大权重值)区间内的随机数。
    • 遍历权重列表, 比较权重值与随机数的大小, 如果权重值大于等千随机数, 就拿当前权重列表的索引值去服务实例列表中获取具体的实例。 这就是在上 一 节中提到的服务实例会根据权重区间挑选的原理,而权重区间边界的开闭原则根据绊法, 正常每个区间为(x, y)的形式, 但是第 一 个实例和最后 一 个实例为什么不同呢?由于随机数的最小取值可以为0, 所以第 一 个实例的下限是闭区间,同时随机数的最大值取不到最大权重值, 所以最后 一 个实例的上限是开区间。
  • ClientConfigEnabledRoundRobinRule:和RoundRobinRule相同,但是通过继承这个策略,则是会将父类的放入备选,实现更高级的策略

  • BestAvailableRule:可选出最空闲的实例。该策略继承自ClientConfigEnabledRoundRobinRule, 在实现中它注入了负载均衡器的 统计对象 LoadBalancerStats , 同时在具体的 choose 算法中利用LoadBalancerStats 保存的实例统计信息来选择满足要求的实例。从源码中我们可以看到, 它通过遍历负载均衡器中维护的所有服务实例, 会过滤掉故障的实例, 并找出并发请求数最小的 一 个;
    该算法的核心依据是统计对象 loadBalancerStats, 当其为空的时候,该策略是 无法执行的,所以就会使用父类的轮询算法

  • PredicateBasedRule:继承自ClientConfigEnabledRoundRobinRule,是基于Google Guava Collection 工具对集合进行过滤之后的实例,然后进行选择,先通过子类中实现的 Predicate 逻辑来过滤 一 部分服务实例, 然后再以线性轮询的方式从过滤后的实例清单中选出 一 个。

  • AvailabilityFilteringRule,继承于PredicateBasedRule.过滤条件为
    • 是否故障, 即断路器是否生效已断开。
    • 实例的并发请求数大于阙值,默认值为 2^32 - 1,
    该配置可通过参数 ..ActiveConnectionsLimit 来修改。

  • ZoneAvoidanceRule:继承于PredicateBasedRule.使用了 CompositePredicate 来进行服务实例清单的过滤,以ZoneAvoidancePredicate 为主过滤条件, AvaliabilityPredicate 为次过滤条件 初始化了组合过滤条件的实例
    • 使用主过滤条件对所有实例过滤并返回过滤后的实例清单。
    • 依次使用次过滤条件列表中的过滤条件对主过滤条件的结果进行过滤。
    • 每次过滤之后(包括主过滤条件和次过滤条件),都需要判断下面两个条件, 只要有
    一个符合就不再进行过滤, 将当前结果返回供线性轮询算法选择:
    . 过滤后的实例总数>=最小过滤实例数(皿 nima!FilteredServers, 默认为 1) 。
    . 过滤后的实例比例>最小过滤百分比 (minima!Filtered.Percentage, 默认为 0) 。
    在这里插入图片描述

  • 具体的配置
    在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!