Brendan Burns:designing Distributed Systems——patterns And Paradigms For Scalable, Reliable Services@2018

本文件核心論點圍繞於如何在當前複雜且需求多樣的數位環境中,有效率且可靠地設計與建構分散式系統。文件開宗明義指出,由於現代應用程式需要具備高可用性、可靠性及快速擴展能力,幾乎所有應用程式都必須是分散式系統。然而,建構分散式系統的挑戰在於其複雜性,傳統上常被視為一種需要高度專業知識的「黑魔法」。

文件強調,近期容器與容器編排工具(例如 Kubernetes)的興起,為分散式系統開發帶來了根本性的變革。這些技術提供了標準化的建構區塊,即容器,以及管理這些區塊的平台。這使得定義和應用可重複使用的模式 (patterns) 及元件 (components) 成為可能,從而大幅簡化分散式系統的設計與開發過程。

主要論點及其詳盡解釋如下:

  1. 分散式系統的必要性與挑戰:

    • 必要性: 文件指出,隨著現代應用程式對高可用性 (High Availability)、可靠性 (Reliability) 和快速擴展能力 (Scalability) 的需求日益增加,單機應用程式或簡單的客戶端-伺服器架構已不足以應付。應用程式需要分散運行在多台機器上,形成分散式系統,以確保在部分節點失效時服務仍能持續,並能隨著使用者需求增長而擴展。無論是行動應用程式後端還是企業級支付平台,分散式架構都已成為標準。
    • 挑戰: 與單機應用程式不同,分散式系統涉及多個協作元件、網路通訊、狀態管理、容錯處理等複雜議題。這使得設計、建構和除錯分散式系統變得異常困難,所需的工程技能水平遠高於單機應用程式。傳統上,這類系統往往是客製化的一次性解決方案,缺乏標準化的方法和工具。
  2. 模式、實踐與可重複使用元件的價值:

    • 歷史借鑒: 文件透過回顧軟體開發史中的類似轉變(例如 Donald Knuth 對演算法的形式化,以及 GoF 書籍對物件導向設計模式的普及),說明模式在軟體開發進程中的關鍵作用。模式為複雜問題提供了通用的解決方案藍圖和共享語言。
    • 模式的價值:
      • 站在巨人的肩膀上: 模式是對前人經驗和錯誤教訓的總結,讓開發者無需從零開始,加速學習和應用成熟的設計理念,提升效率和可靠性。
      • 共享語言: 模式提供了一套共同的詞彙和定義,便於開發者之間快速理解和交流複雜的分散式系統概念,減少溝通障礙,促進知識分享。
      • 實現可重複使用的元件: 模式識別出系統中常見的、可抽象化的結構和功能,這促使了通用、可重複使用元件(例如函式庫、框架)的開發。在分散式系統中,容器化使得將這些模式實現為可部署的元件(如容器映像檔)成為可能,這些元件可以在不同的應用程式中重用,節省開發時間,提高品質。
  3. 容器與容器編排作為分散式系統的基礎:

    • 文件明確指出,容器 (Containers) 和容器編排器 (Container Orchestrators) 是實現現代分散式系統模式的基礎。容器提供了一種標準化的打包和運行應用程式的方式,為應用程式提供了資源邊界 (resource isolation)、團隊擁有權劃分 (team ownership) 和關注點分離 (separation of concerns)。
    • 容器編排器負責大規模地部署、擴展、管理和自癒容器化應用程式。它提供了跨多機調度的能力、服務發現、負載平衡、自動重啟等分散式系統運行所需的底層機制。
    • 容器與編排器的結合,使得模式不再僅僅是抽象的設計概念,而是可以透過具體的容器組合和管理策略來實現和部署的實體。
  4. 不同層次的分散式系統模式分類:

    • 文件將分散式系統模式分為幾個主要類別,反映了系統設計中不同的關注點和抽象層次:
      • 單節點模式 (Single-Node Patterns): 這類模式關注在同一物理或虛擬機器上協同運行的多個容器。雖然是單節點,但這些模式利用容器組(如 Kubernetes 的 Pod)的特性(共享網路命名空間、檔案系統等)來實現應用程式的模組化、增強功能或適配介面。範例包括:
        • 副車模式 (Sidecar Pattern): 一個容器(副車)增強或擴展主應用程式容器的功能,通常對主應用程式是透明的(例如:為舊服務添加 HTTPS、動態配置同步)。
        • 大使模式 (Ambassador Pattern): 一個容器(大使)作為主應用程式容器與外部世界的橋樑,代理或 brokering 應用程式的通訊(例如:分片服務的客戶端代理、服務發現代理)。
        • 適配器模式 (Adapter Pattern): 一個容器(適配器)修改主應用程式容器的介面,使其符合標準化的介面(例如:將不同格式的日誌或監控資料轉換為標準格式)。
      • 服務模式 (Serving Patterns): 這類模式關注如何部署和管理長時間運行、響應即時請求的服務,通常跨越多個節點。
        • 複製負載平衡服務 (Replicated Load-Balanced Services): 簡單地複製無狀態服務實例,並透過負載平衡器分散請求,以提供高可用性和水平擴展能力。討論了無狀態服務、會話跟蹤服務、以及應用層(如快取、SSL 終止)的複製。
        • 分片服務 (Sharded Services): 當服務狀態(資料量)過大無法由單機處理時,將資料分割成多個片段 (shards),每個片段由特定的服務實例處理。討論了分片快取、分片函數的選擇(鍵、一致性雜湊)。
        • 分散/聚合 (Scatter/Gather): 將單一請求分散到多個節點並行處理,然後在根節點聚合結果。用於加速請求處理(計算的分片),特別適合可並行計算的問題(例如:文件搜索、聚合查詢)。討論了如何擴展以提高可靠性和規模。
        • 函數即服務 (FaaS) 與事件驅動處理: 一種以請求或事件為基礎的短期計算模型。適合無狀態、事件觸發的任務。討論了 FaaS 的優劣、應用場景(如裝飾器、事件處理、事件管線)。
        • 所有權選舉 (Ownership Election): 在需要某項資源(如資料分片、特定任務)只能由單一服務實例擁有的狀態服務中,如何可靠地選擇和管理所有者(主節點),並在所有者失效時進行故障轉移。討論了主節點選舉的機制和挑戰。
      • 批次計算模式 (Batch Computational Patterns): 這類模式關注如何處理大量、通常非即時的資料集。
        • 工作佇列系統 (Work Queue Systems): 將需要處理的任務分解成獨立的工作項,放入佇列中,由多個工作者並行處理。討論了通用的工作佇列架構、源容器介面、工作者容器介面以及如何動態擴展。
        • 事件驅動批次處理 (Event-Driven Batch Processing): 將複雜的批次處理流程分解為由事件連接的多個階段或工作佇列,形成工作流。討論了串聯、複製、過濾、分發、合併等模式,以及發布/訂閱 (Pub/Sub) 基礎設施的作用(例如:Kafka)。
        • 協調批次處理 (Coordinated Batch Processing): 討論需要多個並行處理階段之間進行協調的批次模式,特別是涉及結果聚合的場景。範例包括結合 (Join/Barrier Synchronization) 和規約 (Reduce) 等。
  5. 新時代的開發前景:

    • 文件在結論中再次強調,容器和容器編排工具,結合本書闡述的這些模式,提供了一個新的起點,可以讓分散式系統開發變得更快、更容易、更可靠。鼓勵開發者超越從零開始建構系統,轉而協作開發通用、可重複使用的模式實現,從而提高整體開發效率,並擴大能夠建構複雜分散式系統的開發者群體。

總而言之,文件核心論點是:面對現代應用程式對分散式系統的迫切需求,容器和容器編排技術提供了新的基礎設施,而通用且可重複使用的設計模式則是充分發揮這些技術潛力、克服分散式系統固有複雜性、並實現可靠、可擴展、敏捷開發的關鍵方法。透過學習和應用這些模式,開發者可以更有效地建構滿足當前及未來需求的數位化服務。