共用方式為


艙壁模式

Bulkhead 模式是一種容忍失敗的應用設計。 在隔板架構(又稱 單元架構)中,應用程式的元素被隔離成池子,若其中一個元件失敗,其他元件仍能繼續運作。 隔艙設計的名稱來自於船體的分段隔板(bulkheads)。 如果船隻的船體受損,只有受損的區段會被水填滿,這樣可防止船隻沉沒。

內容和問題

雲端應用程式可能包含多個服務,每個服務都有一個或多個消費者。 服務負載過重或故障會影響所有服務使用者。

此外,消費者可能同時向多個服務發送請求,並對每個請求使用資源。 當消費者向設定錯誤或無回應的服務發送請求時,客戶端請求所使用的資源可能會長時間無法使用。 當服務請求繼續進行時,這些資源可能會耗盡。 例如,用戶端的連線集區可能已耗盡。 此時,消費者對其他服務的請求也會受到影響。 最終,消費者無法向其他服務發送請求,而非原本無回應的服務。

資源耗盡會影響擁有多位消費者的服務。 來自同一客戶端的多個請求可能會耗盡服務中可用的資源。 資源耗盡可能意味著其他消費者無法使用該服務,進而引發連鎖故障。

解決方案

根據消費者負載與可用性需求,將服務實例劃分為不同群組。 這種設計有助於隔離故障。 即使在故障發生時,某些使用者仍能維持服務功能。

消費者也可以分割資源,確保呼叫一個服務的資源不會影響呼叫另一個服務的資源。 例如,呼叫多個服務的消費者可能會為每個服務分配一個連線池。 如果服務開始失敗,只會影響該服務所分配的連線池。 消費者可以繼續使用其他服務。

此模式提供下列優點:

  • 隔離消費者和服務與連鎖故障。 影響消費者或服務的問題可以被隔離在自己的隔板內,以防止整個解決方案失敗。

  • 若發生服務故障,保留部分功能。 應用程式的其他服務與功能仍持續運作。

  • 為消費者應用程式提供不同的服務品質等級。 你可以設定高優先權的消費者池來使用高優先權的服務。

下圖顯示了圍繞連接池結構的隔板,這些連接池用於呼叫個別服務。 若服務 A 失敗或造成問題,連線池會被隔離,因此只有使用分配給服務 A 的執行緒池的工作負載會受到影響。 使用服務 B 和 C 的工作負載不會受到影響,而且可以繼續運作而不會中斷。

圖示顯示隔艙圍繞著用於呼叫個別服務的連線池結構。

圖示顯示兩個工作負載,工作負載 1 和工作負載 2,以及三個服務,分別是服務 A、服務 B 和服務 C。工作負載 1 使用分配給服務 A 的連線池。工作負載 2 使用兩個連線池。 一個連線池分配給服務B,另一個分配給服務C。工作負載 1 使用的連線池是隔離的。 工作負載2所使用的連線池可以繼續呼叫服務B和服務C。

下圖顯示多個用戶端呼叫單一服務。 每個用戶端都被指派到一個獨立的服務實例。 客戶端 1 請求過多,導致實例不堪負荷。 由於每個服務實例彼此隔離,其他用戶端仍可繼續呼叫。

圖示顯示多個客戶端呼叫同一服務。

圖示顯示三個客戶端,分別是客戶端 1、客戶端 2 和客戶端 3,以及三個服務實例,各自屬於服務 A。每個用戶端都會連接到自己的服務實例。 服務實例是隔離的。 如果用戶端 1 讓其實例過載,用戶端 2 和 3 則不受影響。

問題和考慮

在決定如何實施此模式時,請考慮以下幾點:

  • 定義應用程式商務和技術需求周圍的分割區。

  • 如果你使用 戰術領域驅動設計來設計微服務,分割邊界應該與有界上下文對齊。

  • 當你將服務或消費者劃分為分區時,請考慮技術所提供的隔離程度,以及成本、效能和管理的額外成本。

  • 為了提供更精密的故障處理,可以考慮將隔艙與重試、斷路器及節流模式結合起來。

  • 當你將消費者劃分為艙壁時,可以考慮使用程序、執行緒池和信號量。 resilience4jPolly專案提供建立消費者隔艙的架構。

  • 當你將服務劃分為多個區塊時,可以考慮將它們部署到不同的虛擬機、容器或程序中。 容器在資源隔離方面提供了良好的平衡,額外負荷相當低。

  • 使用非同步訊息通訊的服務可透過不同的佇列集合被隔離。 每個佇列可以有專門的實例組處理該佇列上的訊息,或是一組使用演算法進行去佇列與派遣處理的實例。

  • 判斷隔板的細節程度。 例如,如果你想將租戶分散到不同的分割區,你可以將每個租戶放在獨立的分割區,或是將多個租戶放在一個分割區。

  • 監控每個分割區的效能與服務水準協議(SLA)。

  • 使用內建的平台控制功能,例如 Azure API 管理速率限制、Azure Cosmos DB 請求單元(RU)隔離,以及 Azure Kubernetes Service(AKS)或 Azure 容器應用中的資源限制。 不要在你的應用程式程式碼中重現這些限速和隔離機制。

  • AI 與推論工作負載常因部署配額與並發限制而必須採取嚴格的隔離措施,例如將 Azure OpenAI 部署隔離為每個工作負載或每個租戶。

使用此模式的時機

當下列情況時,請使用此模式:

  • 你要為特定相依性隔離資源,這樣單一服務的中斷就不會影響整個應用程式。
  • 你要把關鍵消費者和一般消費者分開。
  • 你需要保護應用程式免於連鎖故障。

在下列情況下,此模式可能不適用:

  • 在專案中,資源使用效率較低可能是不可接受的。
  • 額外的複雜度並非必要。

工作負載設計

評估如何在工作負載設計中使用 Bulkhead 模式,以達成 Azure Well-Architected Framework 支柱所涵蓋的目標與原則。 下表提供此模式如何支援每個要素目標的指引。

支柱 此模式如何支援支柱目標
可靠性 設計決策有助於使工作負載具有韌性,並確保在故障發生後能復原到正常運作的狀態。 透過有意識且完整的組件分割,所引入的失效隔離策略試圖將故障限制在遇到問題的隔板,從而防止其他隔板受到影響。

- RE:02 關鍵流程
- RE:07 自我保護
安全性 設計決策有助於確保 工作負載數據和系統的機密性完整性可用性 元件之間的分割有助於將安全事件限制在已入侵的隔板中。

- SE:04 分段
效能效率 可透過調整、數據和程式碼的優化, 有效率地協助您的工作負載符合需求 每個隔板可以獨立調整,以有效配合隔板內的任務需求。

- PE:02 容量規劃
- PE:05 縮放和分區

如果此模式在一個支柱內部引入取捨,請將它們與其他支柱的目標進行考量。

範例

下列 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"

下一步