一.熔断策略目标
1) 支持基于异常比例(失败率)的熔断策略、支持慢调用(响应时间)比例的熔断策略。
2) 支持交易维度的熔断、支持服务端协议维度的熔断,抛异常后被熔断器感知到就可实现。
3) 支持动态配置、开关启停、Prometheus监控
二.熔断状态切换
三.熔断流程
四.熔断器参数设置
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofMillis(1000))
.ringBufferSizeInHalfOpenState(2)
.ringBufferSizeInClosedState(2)
.recordExceptions(IOException.class, TimeoutException.class)
.ignoreExceptions(BusinessException.class, OtherBusinessException.class)
.enableAutomaticTransitionFromOpenToHalfOpen()
.build();
当然,也可以使用默认的熔断器配置,这样就不需要定制化熔断器了。
2.1 sliding-window-type :断路器的滑动窗口期类型可以基于“次数”(COUNT_BASED)或者“时间”(TIME_BASED)进行熔断,默认是COUNT_BASED。
2.2 failure-rate-threshold=50 默认50%,设置50%的调用失败时打开断路器。
2.3 sliding-window-size=10 若COUNT_BASED,则10次调用中有50%失败(即5次)打开熔断断路器;若为TIME_BASED则表示秒数,此时有额外的两个设置属性,含义为:在10秒内(sliding-window-size)100%(slow-call-rate-threshold)的请求超过2秒(
slow-call-duration-threshold)打开断路器。
slow-call-rate-threshold=100
slow-call-duration-threshold=2000
2.4 permitted-number-of-calls-in-half-open-state=3 运行断路器在HALF_OPEN状态下时进行3次调用,如果故障或慢速调用仍然高于阈值,断路器再次进入打开状态。
2.5 minimum-number-of-calls=5 最小调用值。在每个滑动窗口期,配置断路器计算错误率或者慢调用率的最小调用数。本例中设置的5意味着,在计算故障率之前,必须至少调用5次。如果只记录了4次,即使4次都失败了,断路器也不会进入到打开状态。
2.6 wait-duration-in-open-state=5s 一旦断路器是打开状态,它会拒绝请求5秒钟,然后转入半开状态。用来指定断路器从OPEN到HALF_OPEN状态等待的时长,默认是60秒
2.7 ringBufferSizeInClosedState(10) //半熔断时环的容量大小,默认为10
2.8 enableAutomaticTransitionFromOpenToHalfOpen() //自动从OPEN切换到HALF_OPEN
2.9 ringBufferSizeInHalfOpenState(10) 设置当断路器处于HALF_OPEN状态下的ring buffer的大小,它存储了最近一段时间请求的成功失败状态,默认为10
3.0 recordExceptions(ChannelException.class) //设置统计的异常,其它异常不统计
更多关于断路器的配置可参考官方文档:
https://resilience4j.readme.io/
Spring Boot使用Resilience4j容错:熔断、重试、限时、限流、隔板
// 熔断器配置,这里将触发熔断器开启的缓冲器大小设置为2,也就是说目标函数调用失败2次就会导致熔断器开启
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.ringBufferSizeInClosedState(2)
.waitDurationInOpenState(Duration.ofMillis(1000))
.build();
CircuitBreaker circuitBreaker = CircuitBreaker.of("testName", circuitBreakerConfig);
五.熔断业务
1.熔断的初始化
我们会在out容器启动的时候进行熔断初始化,因为我们要支持交易维度和协议维度的熔断,
所以在实体类里面我们有协议名称protocol和服务场景码serviceId俩个字段,
协议名称是一定有的,但服务场景码可以为空,当为空的时候我们会为场景码赋值为ALL,
最后,我们会把初始化好的熔断器封装到一个map集合里面,key为协议名称_服务场景码,value为初始化好的熔断器。至于,初始化所用的数据来源于apollo,在apollo中我们配置为:key为协议名称_服务场景码,value为用来初始化熔断器的json数据。
在apollo中,我们配置了默认的熔断器规则,default_adapter为key,值为默认熔断规则的json数据。还配置了自定义的熔断规则,上面已经提及过了。我们会为所有的协议生成对应的熔断器,apollo已经配置的我们称为自定义熔断器,但后端还有很多协议没有配置我们就为其设置默认的熔断规则。
未配置协议=out端所有协议-自定义协议,然后为没有配置的协议设置默认的熔断规则。
2.熔断的判断
所有发向out端的请求都会经过DefaultBuinessService,在DefaultBuinessService里conn.send前新增熔断功能,当熔断开关开启时进行熔断判断。
执行到此处,我们可以获取到请求的协议名称和服务码,然后找到对应熔断器map集合中的熔断器,让熔断器去执行业务方法,仅当业务方法抛异常或者超时,才会触发熔断。
3.熔断的监控
熔断一但触发,熔断器内部就监控器会记录失败率等信息,我们只要定时遍历熔断器集合获取其中的监控信息,然后把这些监控数据上传到普罗米修斯就实现了熔断的监控功能。
4.动态修改熔断策略
因为我们的熔断器初始化数据是保存在apollo,所以当初始化熔断器配置数据发生改变时,我们的熔断器也应该实时感知并更新,使用apollo的监听机制就可实现。
一但监听到有有熔断规则数据发生变化,就重新生成熔断器集合。
监听熔断配置:
描述:
- 新增或修改,重新生成对应熔断器注册器和熔断器。
- 复制原断路器集合,删除变更的断路器,加入新的断路器。
- 替换原断路器集合。
- 删除下,需取默认配置生成新的断路器,其他流程同新增。
更新时,熔断配置会重新构造熔断器集合,内存中原熔断器集合会重置,包括所有熔断器状态,所有熔断器计数。如:本来是全开状态下的熔断器也会重置成关闭。我们使用了cas锁进行熔断器集合替换。
5.熔断开关启停热生效功能
因为apollo不让放熔断总开关,所以就放到了内管上,当修改后点击下发,会触发PushModifyAllocationInvoker的invoke方法,我们在这里修改项目中熔断总开关的状态,实现热生效功能。