java系统找不到指定文件怎么解决
308
2022-08-23
【微服务六】Ribbon负载均衡策略之轮询(RoundRobinRule)、重试(RetryRule)
文章目录
一、前言二、轮询算法 --> RoundRobinRule三、重试算法 --> RetryRule
一、前言
前置Ribbon相关文章:
【云原生&微服务一】SpringCloud之Ribbon实现负载均衡详细案例(集成Eureka、Ribbon)【云原生&微服务二】SpringCloud之Ribbon自定义负载均衡策略(含Ribbon核心API)【云原生&微服务三】SpringCloud之Ribbon是这样实现负载均衡的(源码剖析@LoadBalanced原理)【云原生&微服务四】SpringCloud之Ribbon和Erueka集成的细节全在这了(源码剖析)【微服务五】Ribbon随机负载均衡算法如何实现的
我们聊了以下问题:
为什么给RestTemplate类上加上了@LoadBalanced注解就可以使用Ribbon的负载均衡?SpringCloud是如何集成Ribbon的?Ribbon如何作用到RestTemplate上的?如何获取到Ribbon的ILoadBalancer?ZoneAwareLoadBalancer(属于ribbon)如何与eureka整合,通过eureka client获取到对应注册表?ZoneAwareLoadBalancer如何持续从Eureka中获取最新的注册表信息?如何根据负载均衡器ILoadBalancer从Eureka Client获取到的List
本文继续讨论 轮询(RoundRobinRule)、重试(RetryRule)是如何实现的?
PS:Ribbon依赖Spring Cloud版本信息如下:
二、轮询算法 --> RoundRobinRule
我们知道Ribbon负载均衡算法体现在IRule的choose(Object key)方法中,而choose(Object key)方法中又会调用choose(ILoadBalancer lb, Object key)方法,所以我们只需要看各个IRule实现类的choose(ILoadBalancer lb, Object key)方法;
随机算法体现在RoundRobinRule#incrementAndGetModulo()方法:
private AtomicInteger nextServerCyclicCounter;private int incrementAndGetModulo(int modulo) { // 死循环直到获取到一个索引下标 for (;;) { // 获取当前AtomicInteger类型变量的原子值 int current = nextServerCyclicCounter.get(); // 当前原子值 + 1 然后对 服务实例个数取余 int next = (current + 1) % modulo; // CAS修改AtomicInteger类型变量,CAS成功返回next,否则无限重试 if (nextServerCyclicCounter.compareAndSet(current, next)) return next; }}
轮询算法很简单,重点在于通过AtomicInteger原子类型变量 + 死循环 CAS操作实现,每次返回原子类型变量的当前值 + 1,因为原子类型变量可能超过服务实例数,所以每次对原子类型变量赋值时,都会对其和服务实例总数做取余运算。
三、重试算法 --> RetryRule
进入RetryRule的choose(ILoadBalancer lb, Object key)方法;
方法的核心逻辑:
首先记录开始要选择一个服务实例时的时间(即:开始请求时间为当前时间),和允许获取到服务实例的deadline,deadline为当前时间 + 500ms;接着使用RetryRule组合的RoundRobinRule轮询选择一个服务实例;如果选择的服务实例为空并且当前时间还没到deadline 或 选择的服务实例不是活着的并且当前时间还没到deadline,则进行重试、重新获取一个服务实例;重试之前会先启动一个延时(deadline-当前时间)执行的定时任务,其中负责到deadline时中断当前线程;死循环(当前线程不是中断状态时),调用RoundRobin算法选择一个服务实例,如果这个服务实例是有效的 或 当前时间过了截止时间,则跳出循坏;并取消上面新建的延时执行的定时任务,返回当前实例;如果服务实例不是活着的并且当前时间在截止时间之内,则调用Thread.yield(),让出线程资源,使当前线程 或 相同优先级的其他线程可以获取运行机会,也就是说yield的线程有可能被线程调度程序再次选中执行。
所以:RetryRule在subRule.choose(String)获得无效的服务实例后,会一直重试,但重试次数取决于重试的deadline、当前线程相同优先级的其他线程个数。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~