circuit-breaker

Aug 08 2019

在分布式系统中,对远程服务的调用很可能会临时性失败(如网络连接超时或资源过载等)。这些故障通常会在短时间内自我修复,通常我们在搭建一个可靠的分布式系统时,会通过重试策略来应对这些问题。

但是,也有可能会遇到一些意外事件导致的故障,这种故障可能会需要比较长的时间才能修复。在这种情况下,应用程序重试多少次都是失败的,而且如果此时并发很大,这些毫无意义的重试很有可能把整个服务拖垮。所以,在这种情况下,应该是让应用程序快速认识到操作已失败,并相应地处理故障。

解决方案

断路器模式可以防止应用程序重复尝试执行很可能会失败的操作。在发生故障期间,让它快速失败进入兜底逻辑,不用浪费 CPU 周期。 断路器模式还可让应用程序检测故障是否已经解决。 如果问题已被修复,应用程序便可以尝试调用操作。

断路器模式的目的与重试模式不同。 重试模式在预期操作将成功的情况下让应用程序重试操作。 断路器模式则防止应用程序执行很可能失败的操作。 应用程序可以使用重试模式通过断路器调用操作,来组合这两种模式。 但重试逻辑应该对断路器返回的任何异常保持敏感,并且在断路器指示故障为非临时性的情况下放弃重试尝试。

针对可能失败的操作,断路器充当其代理。代理监控最近发生失败的次数,并使用此信息来决定是执行正常的逻辑还是兜底逻辑或者是直接返回异常。

断路器状态机

半开状态对于防止恢复服务突然被大量请求压垮很有用。 在服务恢复的期间,能够支持的请求数量有限,如果突然有大量的请求可能导致服务超时或再次失败。

断路器状态机

在图中,关闭状态所使用的失败计数器是基于时间的。 它会定期自动重置。 这有助于防止断路器在遇到偶然失败时进入打开状态。 仅当在指定间隔期间内发生指定数量的失败时,才会达到将断路器跳闸到打开状态的故障阈值。 半开状态使用的计数器记录成功调用操作的次数。 在指定数量的连续操作调用成功后,断路器将恢复到关闭状态。 如果任何调用失败,断路器会立即进入打开状态,成功计数器会在下次进入半开状态时重置。

断路器模式在系统从故障中恢复时提供稳定性,并将对性能的影响降至最低。 它可以通过快速拒绝很可能失败的操作的请求(而非等待操作超时或永不返回)来帮助维持系统的响应时间。 如果断路器在每次改变状态时引发事件,则该信息可以用于监视由断路器保护的系统部分的运行状况,或者当断路器跳闸到打开状态时,对管理员发出警报。

该模式是可自定义的,并且可以根据可能的故障类型进行调整。 例如,可以向断路器应用可递增的超时计时器。 最开始可以将断路器置于打开状态几秒钟,如果故障未得到解决,则将超时增加到几分钟,以此类推。 在某些情况下,与其通过打开状态返回失败并引发异常,返回对应用程序来说有意义的默认值实则更加有用。