隔板模式(Bulkhead)

将应用程序的元素隔离到池中,如果其中一个失败,不影响其它继续运行。 这种模式被命名为“隔板”,因为它类似于船体的剖面划分。 如果一艘船的船体受到损害,只有损坏的部分会充满水,从而防止船舶沉没。

背景和问题

基于云的应用可能包括多个服务,每个服务拥有一个或多个消费者。服务负载过多或故障将影响所有消费者。

此外,消费者可以同时向多个服务发送请求,每个请求都消耗资源。当消费者向错误配置或未响应的服务发送请求时,客户端请求使用的资源可能无法及时释放。继续对服务的请求会耗尽这些资源。例如,客户端的连接池可能会耗尽。在这一点上,消费者对其它服务的请求也受到影响。最终,消费者不能再向其它服务发送请求,而不仅仅是原始的无响应服务。

资源耗尽问题同样会影响到多个消费者的服务。来自一个客户端的大量请求可能会耗尽服务中的可用资源。其它消费者不再能够使用该服务,导致级联故障效果。

解决方案

根据消费者的负载和可用性要求,将服务实例分成不同的组。这样的设计有助于隔离故障,并允许在故障期间,为某些消费者维护服务功能。

消费者还可以划分资源,以确保用于调用一个服务的资源不会影响调用另一个服务的资源。例如,可以为每个服务分配一个调用多个服务的消费者连接池。如果服务开始失败,则它仅影响为该服务分配的连接池,而消费者可以继续使用其它服务。

这种模式的好处包括:

  • 隔离消费者和服务级联故障。影响消费者或服务的问题可以在自己的隔板内隔离开来,从而防止整个解决方案发生故障。
  • 允许在发生服务故障时保留一些功能。应用程序的其它服务和功能将继续运行。
  • 允许为消费应用程序部署提供不同服务质量的服务。高优先级消费者池可以配置为使用高优先级服务。

下图显示了围绕呼叫单独服务的连接池构建的隔板。如果服务A失败或导致某些其它问题,则连接池是隔离的,因此只有使用分配给服务A的线程池的工作负载才会受到影响。使用服务B和C的工作负载不受影响,可以继续工作而不中断。

下图显示了多个客户端调用单个服务。 每个客户端分配了一个单独的服务实例。客户端1发出了太多的请求并淹没了它的实例。由于每个服务实例与其它实例隔离,其他客户端可以继续调用。

问题和注意事项

  • 围绕应用程序的业务和技术要求定义分区。
  • 当将服务或消费者分为隔板时,请考虑技术提供的隔离级别以及成本,性能和可管理性方面的开销。
  • 考虑将舱壁与重试,断路器和节流模式相结合,以提供更复杂的故障处理。
  • 将消费者分为隔板时,请考虑使用进程,线程池和信号量。像Netflix HystrixPolly这样的项目提供了创建消费者隔板的框架。
  • 将服务分成隔板时,请考虑将其部署到单独的虚拟机,容器或进程中。容器提供资源隔离的良好平衡,开销相当低。
  • 使用异步消息进行通信的服务可以通过不同的队列进行隔离。每个队列可以具有处理队列上的消息的一组专用实例,或者使用算法进行出队和调度处理的一组实例。
  • 确定隔板的粒度级别。例如,如果要跨分区分配租户,可以将每个租户分成一个单独的分区,将多个租户放入一个分区。
  • 监视每个分区的性能和SLA。

何时使用该模式

在以下场景使用该模式:

  • 隔离用于消耗一组后端服务的资源,特别是如果应用程序可以提供一定程度的功能,即使其中一个服务没有响应。
  • 隔离标准消费者和关键消费者。
  • 保护应用免受级联故障的影响。

这种模式可能不适用于:

  • 项目无法接受资源使用效率低的情况。没有必要增加的复杂性。

案例

下面的Kubernetes配置文件创建一个独立的容器来运行单个服务,拥有自己的CPU和内存资源和限制。

apiVersion: v1
kind: Pod
metadata:
  name: drone-management
spec:
  containers:
  - name: drone-management-container
    image: drone-service
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "1"

相关指南

results matching ""

    No results matching ""