断路器模式为在从错误中恢复的系统提供稳定性,同时降低对性能的影响。它通过快速驳回可能失败的请求来降低系统响应时间。如果每次断路器切换状态时都触发一个时间,则可以用来监视断路器保护部分的系统状态,或在断路器切换到 打开状态时为管理员提供报警。
这个模式是可定制的,而且可适配不同类型的错误。例如,你可以将超时计数器的值调高,你可以将断路器处在开状态的初始值设为几秒,然后如果到时后失败未解决将超时器设为几分钟等。在一些情况下,除了让处在开状态的断路器返回失败和异常,也可以将其配置为返回一个对应用有意义的默认值。
问题和注意事项当考虑如何实现该模式时,需要考虑如下问题:
异常处理。应用通过断路器调用服务需准备好如何处理因服务无法访问而产生的异常。处理异常的方式因应用不同而不同。例如,应用应能临时降级它对应的功能,调用候选的能获得同样数据的应用,或向用户报告错误,请其过后重试。
异常的类型。请求可能由于各种原因而失败,其中一些导致的问题可能比其他更严重。例如,请求可能由于外部服务宕机而失败从而中断数分钟,或者由于服务过载而导致超时。断路器可能能够检测异常的类型从而使用不同的策略。例如,如果要把断路器设定到 开状态,超时类型到错误次数的阈值要比系统完全不可用的阈值要高很懂。
日志。断路器应该记录所有失败的请求(如何可以,也可以记录成功的)来允许管理员来监控操作的健康状况。
可恢复性。你应该为断路器配置其保护的操作可能的恢复模型。例如,如果断路器在打开状态维持了很长时间,可能导致即使错误已经修复,断路器仍抛出异常。类似的,如果断路器从开到半开的时间太短,可能导致它上下波动,减少应用的响应时间(??没懂)。
测试失败的操作。在开的状态下,除了用计数器来决定何时切换到半开状态,断路器还可以启用一个定时任务来周期性 ping 远端服务来判断该服务是否已可以访问。可以采用尝试调用之前失败的服务的形式,或调用远端服务提供的专门用来测试服务状态的操作,如健康状况健康模式 所描述的那样。
手动重载。对于系统恢复时间波动非常大的系统,提供一个手动重置选项来方便管理员关闭断路器(同时重置失败计数器)是很有用的。类似的,如果断路器所保护的服务临时不可用,管理员可以强制打开断路器将其置为开状态(同时重置计时器)。
并发。断路器可能同时被大量客户端访问。其实现不用阻塞并发的请求,也不能给操作添加过多的额外负载。
资源区分。当我们为一个由多个独立的提供者提供的同一个资源使用断路器时,我们需要额外注意。例如,在一个由多个分片的数据存储资源中,即便其他分片遇到临时错误,单个分片也可以接受完全的访问。如果在这种场景中,这些错误被合并成同一错误,应用可能会在某些分片错误时尝试去访问其他分片,但由于断路器的存在,对其他分片的访问也可能会被阻塞,即使它们可能成功。
加速熔断。有时候返回的错误信息包含足够信息令断路器断路。例如,一个共享资源过载,可直接另断路器断路而避免应用马上重试。
[!注意事项]
一个服务可能在限流时返回 HTTP 429(太多的请求),或者在服务当前不可用时返回 HTTP 503(服务不可用)。HTTP 返回信息中可能包含了额外信息,比如下次重试的间隔时间等。
重放失败的请求。在打开的状态下,除了直接返回失败,断路器也可以将每个请求的详细信息记录到日志中,然后然后在远程资源可访问后,重放该请求。
外部服务不适合的超时。断路器不适合用来保护那些设置了过长超时时长的外部服务。如果超时时间过长,断路器的线程可能阻塞,在这段时间内,其他应用可能耶尝试调用这个服务,从而导致断路器消耗大量的线程。
在以下场景可以使用该模式:
阻止应用访问一个很可能失败的共享的远程服务或资源。
以下场景不应该用该模式:
访问本地资源,比如内存中的数据结构。在这个场景中,使用断路器将为你的系统带来额外的开销。
用来替代业务逻辑中的异常处理。
例子