舱壁模式、熔断器的基本定义
原文链接:https://blog.csdn.net/fly910905/article/details/104090857
舱壁模式、熔断器的基本定义
舱壁隔离(Bulkhead Isolation)
在造船行业,往往使用此类模式对船舱进行隔离,利用舱壁将不同的船舱隔离起来,这样如果一个船舱破了进水,只损失一个船舱,其它船舱可以不受影响,而借鉴造船行业的经验,这种模式也在软件行业得到使用。
**舱壁模式(Bulkhead)**隔离了每个工作负载或服务的关键资源,如连接池、内存和 CPU。使用舱壁避免了单个工作负载(或服务)消耗掉所有资源,从而导致其他服务出现故障的场景。这种模式主要是通过防止由一个服务引起的级联故障来增加系统的弹性。
舱壁模式对于熟悉Docker的软件开发者一定不陌生,Docker通过“舱壁模式”实现进程的隔离,使得容器与容器之间不会互相影响。
Hystrix则使用该模式实现线程池的隔离。通过将每个依赖服务分配独立的线程池进行资源隔离,从而避免服务雪崩。
Hystrix会为每一个Hystrix命令(@HystrixCommand来将某个函数包装成了Hystrix命令,Hystrix框架就会自动的为这个函数实现调用的隔离)创建一个独立的线程池,这样就算某个在Hystrix命令包装下的依赖服务出现延迟过高的情况,也只是对该依赖服务的调用产生影响,而不会拖慢其他的服务。
何时使舱壁模式
使用此模式可以:
- 隔离使用一组后端服务所用的资源,尤其是应用程序可以提供某种功能级别时,即使某个服务未能响应。
- 将关键使用者与标准使用者相隔离。
- 防止应用程序发生连锁故障。
此模式可能不适用于以下情况:
- 项目中可能不接受资源的低效利用。
- 没有必要提高复杂性
熔断器(Circuit Breaker)
在我们的工程实践中,偶尔会遇到一些服务由于网络连接超时,系统有异常或load过高出现暂时不可用等情况,导致对这些服务的调用失败,可能需要一段时间才能修复,这种对请求的阻塞可能会占用宝贵的系统资源,如:内存,线程,数据库连接等等,最坏的情况下会导致这些资源被消耗殆尽,使得系统里不相关的部分所使用的资源也耗尽从而拖累整个系统。在这种情况下,调用操作能够立即返回错误而不是等待超时的发生或者重试可能是一种更好的选择,只有当被调用的服务有可能成功时我们再去尝试。
熔断器模式可以防止我们的系统不断地尝试执行可能会失败的调用,使得我们的系统继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器模式也可以使我们系统能够检测错误是否已经修正,如果已经修正,系统会再次尝试调用操作。
何时使用熔断器
使用此模式:
- 防止应用程序尝试调用远程服务或访问共享资源(如果此操作很可能失败)。
不推荐使用此模式:
- 用于处理对应用程序中的本地私有资源的访问,例如内存中数据结构。 在此环境中,使用断路器会增加系统开销。
- 作为处理应用程序的业务逻辑中的异常的替代。
舱壁模式、熔断器的相同点
从设计原则、采取措施、实现效果、异常回退四个维度
设计原则
遵循服务容错的基本原则: “Design for Failure”
服务容错的设计有个基本原则,就是“Design for Failure”。为了避免出现“千里之堤溃于蚁穴”这种情况,在设计上需要考虑到各种边界场景和对于服务间调用出现的异常或延迟情况。这一切都是为了达到以下目标:
1)一个依赖服务的故障不会严重破坏用户的体验。
2)系统能自动或半自动处理故障,具备自我恢复能力。
基于这个原则和目标,衍生出一些模式(舱壁模式、熔断器、超时与重试、回退等),能够解决分布式服务调用中的一些问题,提高系统在故障发生时的存活能力。
采取措施
保护性机制:服务降级
服务降级的措施包括:
- 资源隔离
- 对依赖服务进行分类
- 不可用服务的调用快速失败
资源隔离主要是对调用服务的线程池进行隔离,是舱壁模式的一种实现
对依赖服务进行分类–我们根据具体业务,将依赖服务分为: 强依赖和若依赖. 强依赖服务不可用会导致当前业务中止,而弱依赖服务的不可用不会导致当前业务的中止.
不可用服务的调用快速失败一般通过 超时机制, 熔断器 和熔断后的 降级方法 来实现.
在Hystrix组件中,为了使得故障隔离,它提供的解决方案就包含:舱壁隔离(线程隔离)、超时控制和服务降级、熔断机制的处理
3. 实现效果
降低依赖服务对整个系统的影响,避免了单个服务故障消耗掉所有资源
熔断、舱壁(bulkhead)实现都能够降低依赖服务对整个系统的影响,帮助我们提高系统的可用性
由于服务之间是互相依赖,因此任何组件都可能出错导致用户不能访问。为尽可能减少部分中断带来的影响,我们需要构建容错能力强的服务,以从容应对发生的某些中断。
异常回退
无论是熔断器,还是舱壁隔离模式,它们在使用过程中都会出现异常情况,异常情况的处理方式间接影响到用户的体验,针对异常情况的处理,需要有回退(fallback)策略支撑。
舱壁模式、熔断器的不同点
使用场景不一样
考虑使用舱壁模式,尤其是共享服务模式下。如:kubernetes的pod资源对象具有自身的 CPU 和内存资源与限制。
当外部依赖比较严重,要考虑熔断器的使用
是否增加线程数
使用舱壁隔离模式,会为依赖服务调用维护一个小的线程池,当一个依赖服务由于响应慢导致线程池任务满的时候,不会影响到其他依赖服务的调用,它的缺点就是会增加线程数。
熔断器在在调用异常服务时,能够快速返回结果,避免线程等待,不会增加线程数。
是否提供恢复服务调用的可能
熔断器模式定义了熔断器开关相互转换的逻辑(断路器打开一段时间后,会自动进入半开状态,断路器打开、关闭、半开的逻辑转换)。熔断器的开关能保证服务调用者在调用异常服务时,快速返回结果,避免大量的同步等待,并且熔断器能在一段时间后继续侦测请求执行结果,提供恢复服务调用的可能。
熔断器模式可以使我们系统能够检测错误是否已经修正,如果已经修正,系统会再次尝试调用操作。
舱壁模式则不会有恢复服务调用的可能
参考链接:
https://tech.meituan.com/2016/11/11/service-fault-tolerant-pattern.html
https://docs.microsoft.com/zh-cn/azure/architecture/patterns/bulkhead