一、问题的产生(为什么要引入熔断)
雪崩效应
微服务架构的应用系统通常包含多个服务层。微服务之间通过网络进行通信,从而支撑起整个应用系统,因此,微服务之间难免存在依赖关系。我们知道,任何微服务都并非100%可用,网络往往也很脆弱,因此难免有些请求会失败。
我们常把“基础服务故障”导致“级联故障”的现象称为雪崩效应。雪崩效应描述的是提供者不可用导致消费者不可用,并将不可用逐渐放大的过程。
如下图所示:A作为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,雪崩效应就形成了。
二、如何容错
要想防止雪崩效应,必须有一个强大的容错机制。该容错机制需要实现以下两点。
1.为网络请求设置超时
一次远程调用对应着一个线程/进程。如果响应太慢,这个线程/进程就得不到释放。而线程/进程又对应着系统资源,如果得不到释放的线程/进程越积越多,资源就会被逐渐耗尽,最终导致服务的不可用。
因此,必须为每个网络请求设置超时,让资源尽快释放
2.使用熔断器模式
三、熔断器模式(工作原理)
熔断器的原理很简单,如同电力过载保护器。它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。
熔断器模式就像是那些容易导致错误的操作的一种代理。这种代理能够记录最近调用发生错误的次数,然后决定使用允许操作继续,或者立即返回错误。
熔断器开关相互转换的逻辑如下图:
—正常情况下,断路器关闭,可正常请求服务。
—当一段请求过后,请求失败率达到一定阈值,例如错误率50%,熔断器就会打开,因此,不会再去请求依赖的服务。
—断路器打开一段时间后,会自动进入“半开”状态。此时,熔断器可允许少量请求访问依赖的服务。如果成功,则关闭熔断器;否则继续转为打开状态。
Resilience4j在请求数量达到设置的缓冲池大小时才会进行失败率计算,计算完成后会清空缓冲池,所以熔断的间隔是一轮缓冲池大小,不是每请求失败一次就熔断一次,不是用滑动窗口计算失败率,也跟时间无关,缓冲池逻辑结构图如下所示:
熔断器的环形缓冲池
熔断器就是保护服务高可用的最后一道防线。
Resilience4j CircuitBreaker工作流程图
熔断器方案:Resilience4j CircuitBreaker,Resilience4j retrofit。http://resilience4j.github.io/resilience4j/
Resilience4j CircuitBreaker熔断器核心实现源码:
熔断器通过circuitBreaker.onSuccess(durationInNanos)和 circuitBreaker.onError(durationInNanos, throwable)来统计失败率
|
onSuccess()和onFailure()代码
|