内容简介:结合实际业务需求,在serverStats中,目前定义了两类异常,连接异常(主要指tcp层面的,包括sokcetException,socketTimeoutException,ConnectException)以及不可用异常(主要是底层通信框架rxNetty抛出的异常,包括timeoutException以及PoolExhaustedException)。而其中连接失败异常相关的参数,考虑到较为底层,使用者不大关心,是默认设置好了,只通过读取环境变量的方式来允许改动。
Ribbon是Netflix出品的一套负载均衡组件,提供了许多Rule规则从负载列表中选取合适的server实例。
当实例出现问题时候,需要将这部分异常的服务提供者从负载列表中剔除,从而避免雪崩效应。而Riibbon本身具有自动移除问题实例的功能,于是我们可以结合Ribbon对现有的负载均衡策略做一些改进,实现自动故障剔除功能。工作流程
Ribbon中实现自动移除问题实例的Rule是AvailabilityFilteringRule,它的运行原理如上图所示,大致可以分为以下几步:
- 在LoadbalancerCommand发起choose server请求时候,首先会通过RoundRobinRule去服务器列表serverList获取server,此处RoundRobinRule是修改过的带权重的加权轮询算法器。
- 从RoundRobinRule获取一个server之后,会AvailabilityPredicate这个断言器去判断是否是问题实例。简单来说,就是从LoadBalancerStats中获取这个server的状态serverStats,然后在serverStats这个状态机中去判断是否应该断路。
- 经过serverStats的断路判断之后,如果是需要断路的,那么表明是问题实例,如果不需要,则返回给LoadBalancerCommand一个正常的server实例。
- LoadBalancerCommand在处理完请求后,无论成功与否都对serverStats做一次相应的状态记录。
服务状态ServerStats
结合实际业务需求,在serverStats中,目前定义了两类异常,连接异常(主要指tcp层面的,包括sokcetException,socketTimeoutException,ConnectException)以及不可用异常(主要是底层通信框架rxNetty抛出的异常,包括timeoutException以及PoolExhaustedException)。
参数定义
考虑到两种异常的发生场景的差异,为这两类异常分别设置了各自的连续失败阈值(connectionFailureThreshold,unavailableThreshold)以及断路超时时间(connectionFailureCircuitTimeout,unavailableCircuitTimeout)。
其中不可用异常参数(unavailableThreshold,unavailableCircuitTimeout)会暴露给使用者,使用springboot的项目可以直接读取yml文件或者托管到第三方配置中心。而其中连接失败异常相关的参数,考虑到较为底层,使用者不大关心,是默认设置好了,只通过读取环境变量的方式来允许改动。
断路器工作原理
从上面定义的参数就指定,目前断路器统计失败是靠连续失败次数去判断断路逻辑的。之后可以根据不同场景做不同的适配。
目前断路器的工作算法大致如下- 计算累计连接失败计数successiveConnectionFailureCount 是否超过 链接失败阈值connectionFailureThreshold。如果 successiveConnectionFailureCount < connectionFailureThreshold,即尚未超过限额,则熔断时间为 0 ;反之,如果超过限额,则进行步骤2的计算
- 计算失败基数,最大不得超过 16。diff = (failureCount - threshold) > 16 ? 16 : (failureCount - threshold)
- 根据超时因子timeoutFactor(目前默认写死为10)计算超时时间: blackOutSeconds = (1 << diff) * timeoutFactor;
- 超时时间不得超过最大超时时间connectionFailureCircuitTimeout 上线
- 计算完连接失败异常相应的超时时间connectionFailureblackOutPeriod之后,用不可用异常对应的参数去重复一下1-4步骤算出不可用异常对应的超时时间unavailableblackOutPeriod。两者取最大值作为blackOutPeriod。
- 将最后一次失败时间lastConnectionFailedTimestamp加上blackOutPeriod超时间隔,作为当前断路器刚关闭的时间。
- 每一次请求来,只要比较当前时间与步骤6算出的时间即可,如果当前时间较大,说明过了断路器刚关闭的时间,可以正常提供服务,否则表明服务是断路状态。
当有链接失败情况出现断路逻辑时,将会最多:1<<16 * 10 = 655360 s (如果超过自定义超时时间阈值,则最大为自定义超时时间),最少1<<0*10 = 10 s的请求熔断时间,再此期间内,此Server将会被忽略。
熔断的超时时间在没有超过自定义超时阈值的情况下,会随着该server的失败次数呈指数级动态增加。如果当自定义阈值很大,而一个服务实例连续失败很多次,那他基本就没什么希望被调用到了。。框架中算法实现如下:
private long getCircuitBreakerBlackoutPeriod(AtomicInteger atomicInteger, Integer threshold, Integer circuitTimeout) { final int failureCount = atomicInteger.get(); if (failureCount < threshold) { return 0; } final int diff = (failureCount - threshold) > 16 ? 16 : (failureCount - threshold); int blackOutSeconds = (1 << diff) * timeoutFactor; if (blackOutSeconds > circuitTimeout) { blackOutSeconds = circuitTimeout; } return blackOutSeconds * 1000L; }
记录服务状态
当loadBalancerCommand对服务请求做出处理之后,根据返回的状态对serverStats做出记录。
- 每当服务正常返回时候,会清空两种异常的熔断统计。
- 每当服务异常,但是异常不是定义的两种异常中的任何一种,也会清空两种异常的熔断统计。
- 每当服务异常,并且异常是两种异常中的一种,则会增加相应异常的熔断统计,并刷新最后失败时间lastConnectionFailedTimestamp这一参数。
服务路由规则
AvailabilityFilteringRule通过一定的规则选择合适的server实例。
首先它用roundRobinRule加权轮询算法选取一个sevrer实例。
接着对选出的server实例应用上述的断路算法判断是否应该断路,如果是断路状态,那么将会重新通过roundRobinRule去选择server实例,这里最多重试10次。
如果经过了10次,还没有选出合适的实例,意味着也许所有实例都被熔断了。那么死活还是得挑一个的,这里会通过父类Rule去选择实例,而父类rule的断言器定义的是always true。public Server choose(Object key) { int count = 0; Server server = roundRobinRule.choose(key); while (count++ <= 10) { if (predicate.apply(new PredicateKey(server))) { return server; } server = roundRobinRule.choose(key); } return super.choose(key); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 利用zookeeper实现分布式服务故障自动剔除/服务自动注册的思路
- 游戏中遮挡剔除方案总结
- 通过剔除上下文依赖减弱封装的耦合性
- OpenGL 优化项之面剔除和注意点
- 故障公告:Linux 内核故障导致网站宕机近 1 个小时
- 线上故障处理手册
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
豆瓣,流行的秘密
黄修源 / 机械工业出版社 / 2009-9 / 29.00
380万人为何会齐聚豆瓣? HIN1和SARS是如何传播扩散开的? 贾君鹏何以快速窜红网络? 通过创新扩散的理论的分析和说明,给出了所有这些问题的答案! 这本书从豆瓣的流行现象说开来,应用了创新扩散等传播学道理来解释了豆瓣如何流行起来,同时作者还同时用创新扩散的理论解释了为何会出现世界变平的现象,长尾理论,SARS病毒的高速传播等。 作者以前任豆瓣设计师的身份以自己亲......一起来看看 《豆瓣,流行的秘密》 这本书的介绍吧!