高可用系列文章之二 - 傳統分層架構技術方案

東風微鳴發表於2022-12-18

前文連結

高可用系列文章之一 - 概述 - 東風微鳴技術部落格 (ewhisper.cn)

三 技術方案

3.1 概述

單點是系統高可用最大的風險和敵人,應該儘量在系統設計的過程中避免單點。

保障系統的高可用, 方法論上,高可用保證的原則是「叢集化」(或 「冗餘」), 只有一個單點,該單點當機所有服務都會受影響而不可用;如果有冗餘或備份,其中一個點當機還有其他冗餘或備份節點能夠提供服務。

保證系統高可用,架構設計的核心準則是:冗餘。

有了冗餘之後,還不夠,每次出現故障需要人工介入恢復勢必會增加系統的 MTTR。所以,又往往是透過「自動故障轉移」來實現系統的高可用。

在下面的技術方案中,詳細介紹瞭如何透過冗餘+自動故障轉移來保證系統的高可用特性。

3.2 製造業系統的典型架構

製造業系統一般採用分層架構, 最簡單的典型架構的展示如下:

ℹ️ ​ 備註:

資料庫以 MySQL 為例.

典型架構

常見的系統架構如上, 分為:

  1. 客戶端層: 典型呼叫方式瀏覽器(browser) 和客戶端(client)
  2. 應用服務層: 實現核心應用邏輯, 通常是 HTTP 協議或 TCP 協議. 這一層細分, 往往還包括:
    1. 表示層: 主要是 web 瀏覽頁面;
    2. 業務邏輯層: 對具體問題進行邏輯判斷和執行操作, 同時也是表示層和資料層的橋樑
    3. 可選: 服務層: 如果實現了服務化, 如 SOA 或微服務化, 就會有這一層;
    4. 資料訪問層: 實現對資料的增刪改查等操作, 並將結果反饋到業務邏輯層
    5. 可選: 資料快取層: 快取加速訪問儲存
  3. 資料庫層: 資料庫固話資料儲存.

整個系統的高可用, 是透過對每一層的冗餘+自動故障轉移來綜合實現的.

ℹ️ 備註:

透過更加細化和細緻的分層, 也可以提高可用性. 如將以上架構細化為:

  1. 客戶端層;
  2. 可選新增: 反向代理層
  3. 可選新增: 表示層(Web Server)層
  4. 應用服務層(App Server)層
  5. 可選新增: 服務呼叫層
  6. 可選新增: 快取層
  7. 資料庫層

本文暫不涉及這一內容.

3.3 製造業系統的推薦高可用架構

透過冗餘這一核心原則, 最佳化後的高可用架構如下圖所示:

HA架構

ℹ️ 說明:

  • 實線 : 請求呼叫
  • 點+橫線: 心跳檢測
  • 點虛線: 尚未真實發生的請求呼叫
  • 短橫虛線: 資料庫主從同步
  • "X" - 對應節點當機不可用.

高可用方案調整說明如下:

  1. 在客戶端層和應用服務層之間, 新增: 負載均衡層. 負責將客戶端請求透過某種負載均衡方式科學地負載到應用服務外層;
  2. 負載均衡層: 這一層包含以下2個元件:
    1. NGINX: 負責 TCP/HTTP 請求的負載反向代理/負載均衡;
    2. Keepalived: 負責對外提供單個 IP, 且對 2 臺 NGINX 進行心跳檢測和故障時的故障轉移;
  3. 應用服務層: 應用伺服器至少為 2 個.
  4. 資料庫層: 資料庫進行主從同步, 讀寫分離

ℹ️ 備註:

上圖中, 也畫出了高可用的另一種實施方案, 本文不做詳細討論:

  • 應用橫向拆分: 單體應用(monolithic application)根據重要性進行拆分, 將重要性高的服務和重要性低的服務進行拆分, 單獨部署.
  • 重要性高的應用, 如低延遲類應用, 流水線上應用等;
  • 重要性低的應用, 如高延遲類應用, 報表應用等.

除此之外, 還可以根據實際業務情況進一步將資料庫進行拆分, 本文亦不做詳細討論:

  • 資料庫拆為 2 個庫, 其中一個庫透過資料同步從另一個庫定時(實時或非實時)同步資料. 舉例說明: 業務庫, 報表庫. (業務庫定期同步資料給報表庫)
  • 重要性高的應用, 讀取寫入業務庫;
  • 重要性低的應用. 如報表類應用. 不允許使用業務庫, 而是使用報表庫.

下面逐一進行分層論述.

3.4 客戶端層 -> 負載均衡層 高可用

1578813330834

客戶端層負載均衡層 高可用, 透過負載均衡層的冗餘來實現的. 具體實現方式如下:

至少有 2 臺 nginx, 其中一臺提供服務, 另一臺冗餘以保證高可用. 並透過 Keepalived 的 virtual IP 來提供同一 IP(如上圖為: 1.2.5.6), 透過心跳探測來進行故障檢測和故障轉移.

在上圖中, NGINX 主節點提供對外服務.

當 NGINX 主節點(如: 192.168.0.1)發生當機, Keepalived 能夠探測到, 會自動進行故障轉移, 將流量自動轉移到 NGINX 從節點(如: 192.168.0.2). 由於使用的是相同的 virtual IP(仍為: 1.2.5.6), 這個切換過程對呼叫方是透明的.

1578812475962

3.5 負載均衡層 -> 應用服務層高可用

負載均衡層應用服務層 的高可用, 是透過應用服務層的冗餘來實現的. 在NGINX的配置檔案 nginx.conf 中, 可以透過 upstream 指令配置多個應用伺服器, 並且 nginx 能夠探測到多個應用伺服器的存活性.

應用服務層高可用1

ℹ️ 知識點:

在 NGINX 開源版本中, 如果不使用第三方外掛,NGINX 的存活探測為: 被動探測.

應用服務層 其中一個節點當機的時候, nginx 能夠探測到, 會自動進行故障轉移, 不會將流量分發到發生故障的節點, 而是分發到其他的正常應用伺服器節點, 整個過程由 NGINX 自動完成, 對呼叫方透明.

應用服務層高可用2

3.6 應用服務層 -> 資料庫層高可用

資料庫層建議採用「主從同步, 讀寫分離」架構. 資料庫的高可用, 又可細分為: 「讀庫高可用」 和「寫庫高可用」 兩類.

ℹ️ 備註:

由於製造業採用了多種資料庫, 包括但不限於:

  • Oracle
  • SQL Server
  • MySQL

不同資料庫的高可用解決方案並不完全相同, 所以本文不對資料庫的具體高可用技術做細節描述. 只進行理論論述.(以 MySQL 為例)

常見的資料庫高可用方案有:

  1. MySQL: 主從同步;
  2. Oracle: RAC
  3. SQL Server: Alwayon

3.6.1 讀庫高可用

讀庫高可用, 是透過讀庫的冗餘來實現的.

如果要對讀庫實現高可用, 一般來說至少有 2 個從庫, 資料庫連線池會建立與讀庫的多個連線, 每次請求會路由到這些讀庫.

讀庫高可用1

當讀庫 - 從1發生當機的時候, 應用服務層的資料庫連線池能夠探測到, 會自動的進行故障轉移, 將流量自動遷移到其他的讀庫, 如讀庫 - 從2, 整個過程由資料庫連線池自動完成, 對呼叫方是透明的.

讀庫高可用2

ℹ️ 備註:

需要應用系統或中介軟體的資料庫連線層實現資料庫連線池功能.

3.6.2 寫庫高可用

寫庫的高可用, 是透過寫庫的冗餘來實現的.

以 MySQL 為例, 可以設定兩個 MySQL 雙主同步, 一臺對線上提供服務, 另一臺冗餘以保證高可用.

3.7 技術選型

3.7.1 負載均衡器技術選型

✔️ 選型結果:

  • 負載均衡器: NGINX + Keepalived
  • 版本:
    • NGINX: 1.16.1 (❗ 選型版本至少每半年評估一次, 根據評估結果對版本進行調整)
    • Keepalived: 2.0.10(❗️ 選型版本至少每半年評估一次, 根據評估結果對版本進行調整)
  • 作業系統型別: Linux
  • 作業系統版本: SUSE 12 (按需調整,遵循製造業的相關技術規範要求.)

ℹ️ 定義及概述:

在分散式系統中,負載均衡(load balance)是一種有效的將網路請求分配到多個伺服器的過程。透過將負載進行負載均衡,可以有效地改進系統響應時間,提高系統的可用性。隨著系統變的愈發複雜,使用者增多和網路流量增大,負載均衡已經成為系統設計中的必要一環。

負載均衡器可以是硬體也可以是軟體,它會將網路請求分發到伺服器叢集上。

選型過程概述

常見的硬體負載均衡器包括:

  • F5
  • A10

常見的軟體負載均衡器包括:

  • Nginx
  • LVS
  • HAProxy

結合製造行業最佳實踐, 以及製造業的實際情況考慮, 製造業在全國乃至全球擁有多座工廠, 每個工廠擁有獨立的機房. 採用硬體負載均衡成本過高. 確定採用軟體負載均衡器作為負載均衡技術實現. 下面對軟體負載均衡器逐一進行論述:

NGINX:

Nginx("engine x")是一款是由俄羅斯的程式設計師 Igor Sysoev 所開發高效能的 Web 和 反向代理 伺服器.

優點:

  1. 工作在網路的 4 層(TCP/UDP)和 7 層(HTTP/websocket),可以針對 http 應用做一些分流的策略,比如針對域名、目錄結構,其正則規則比 HAProxy 更為強大和靈活, 同時 NGINX 目前是使用最廣泛的負載均衡器和 Web Server,適用場景豐富.
  2. Nginx 對網路穩定性的依賴非常小,理論上能 ping 通就就能進行負載功能;相反 LVS 對網路穩定性依賴比較大;
  3. Nginx 安裝和配置比較簡單,測試起來比較方便,NGINX 擁有完善的且可自定義的日誌, 包括 access 日誌和 error 日誌。LVS 的配置、測試需要花費比較長的時間。
  4. NGINX 可以承擔高負載壓力且穩定,在硬體不差的情況下很容易能支撐幾萬次的併發量。
  5. Nginx 可以透過埠檢測到應用伺服器的故障,如根據伺服器處理網頁返回的狀態碼、超時等等,並且會把返回錯誤的請求重新提交到另一個節點。如使用者正在上傳一個檔案,而處理該上傳的節點剛好在上傳過程中出現故障,Nginx 會將上傳切到另一臺伺服器重新處理,如果是 LVS就直接斷掉了。
  6. Nginx 不僅僅是一款優秀的負載均衡器/反向代理軟體,它同時也是功能強大的 Web 應用伺服器。LNMP 也是近幾年非常流行的 web 架構,在高流量的環境中穩定性也很好。
  7. Nginx 作為 Web 反向加速緩也比較成熟,速度比傳統的 Squid 伺服器更快,在未來場景用, 也可以擴充套件 NGINX 的用途。
  8. Nginx 可作為反向代理使用,作為反向代理, Nginx 使用最廣泛, 同類產品還有 lighttpd 了,不過 lighttpd 目前還沒有做到 Nginx 完全的功能,配置也不清晰易讀,社群資料也遠遠沒 Nginx 活躍。
  9. Nginx 也可作為靜態網頁和圖片伺服器,這方面的效能也無對手。
  10. Nginx 社群非常活躍,第三方模組也很多。

缺點:

  1. 對後端伺服器的健康檢查, 開源版 NGINX 支援持被動檢測. 不支援主動檢測.
  2. 對於負載均衡的會話保持, 開源版 NGINX 預設不支援cookie會話保持. 但是能透過 ip_hash 實現源地址會話保持, 且可以透過第三方模組實現cookie會話保持.

LVS:

LVS:使用 Linux 核心叢集實現一個高效能、高可用的負載均衡伺服器,它具有很好的可伸縮性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。

優點:

  1. 抗負載能力強、是工作在網路 4 層之上僅作分發之用,沒有流量的產生,這個特點也決定了它在負載均衡軟體裡的效能最強的,對記憶體和cpu 資源消耗比較低。
  2. 配置性比較低,這是一個缺點也是一個優點,因為沒有可太多配置的東西,所以並不需要太多接觸,大大減少了人為出錯的機率。
  3. 工作穩定,因為其本身抗負載能力很強,自身有完整的雙機熱備方案,如 LVS+Keepalived。
  4. 無流量,LVS 只分發請求,而流量並不從它本身出去,這點保證了均衡器 IO 的效能不會收到大流量的影響。
  5. 應用範圍比較廣,因為 LVS 工作在 4 層,所以它幾乎可以對所有應用做負載均衡,包括 http、資料庫、線上聊天室等等。

缺點:

  1. 軟體本身不支援正規表示式處理,不能做動靜分離;而現在許多網站在這方面都有較強的需求,這個是 Nginx+Keepalived 的優勢所在。
  2. 如果是網站應用比較龐大的話,LVS 實施起來比較複雜了,特別後面有 Windows Server 的機器的話,如果實施及配置還有維護過程就比較複雜了,相對而言,Nginx + Keepalived就簡單多了。

HAProxy:

HAProxy 是一個使用 C 語言編寫的自由及開放原始碼軟體,其提供高可用性、負載均衡,以及基於 TCP 和 HTTP 的應用程式代理。

優點:

  1. HAProxy 支援虛擬主機。
  2. HAProxy 的優點能夠補充 Nginx 的一些缺點,比如支援 Session 的保持,Cookie 的引導;同時支援透過獲取指定的 url 來檢測後端伺服器的狀態。
  3. HAProxy 跟 LVS類似,本身就只是一款負載均衡軟體。
  4. HAProxy 支援 TCP 協議的負載均衡轉發。
  5. HAProxy 負載均衡策略比較豐富

缺點:

  1. 不支援 POP/SMTP 協議
  2. 不支援 SPDY 協議
  3. 不支援 HTTP cache 功能。
  4. 過載配置的功能需要重啟程式,雖然也是 soft restart,但沒有 Nginx 的 reload 更為平滑和友好。
  5. 多程式模式支援不夠好

選型結論:

LVS 試用場景單一, 且存在硬傷(即: 後面有Windows Server的機器的話, 實施比較複雜). 直接排除.

HAPorxy 針對 HTTP 的支援沒有 NGINX 豐富, 且重啟中斷相對 NGINX 時間更長.

另外, nginx 除了當前可以用作負載均衡器之外, 還可以用作 web server, http 快取等場景, 且容易上手.

最終確定選擇 NGINX 作為某製造業公司負載均衡器.

3.7.2 NGINX高可用技術方案選型

NGINX 高可用技術方案只有一種, 即: NGINX + Keepalived 實現高可用.

keepalived開源專案包括三個組成部分:

  • keepalivedLinux伺服器的守護程式。

  • 虛擬路由器冗餘協議(VRRP)的實現,用於管理虛擬路由器(虛擬 IP 地址或 VIP)。

    VRRP 確保始終存在一個主節點。備用節點偵聽來自主節點的 VRRP 通告包。如果在超過配置的廣播間隔的三倍的時間內未收到廣播包,則備用節點將作為主節點接管,並將配置的 VIP 分配給自己。

  • 一種執行狀況檢查工具,用於確定服務(例如,Web 伺服器,PHP 後端或資料庫伺服器)是否已啟動並且可以執行。

    如果節點上的服務未透過配置的執行狀況檢查次數,keepalived 則將虛擬 IP 地址從主(主動)節點重新分配給備用(被動)節點。

3.7.3 NGINX 負載均衡策略

✔️選型結果:

負載均衡策略: RR(輪詢, 預設策略)

會話保持策略: (非必須)

  • 不需要會話保持, 則不進行配置.
  • 需要根據源地址進行會話保持: ip_hash

NGINX負載均衡策略:

  1. 輪詢排程演算法: rr (預設排程演算法).
  2. 加權迴圈排程演算法: wrr. 適用場景: nginx伺服器效能不相同, 效能高的需要負載更多請求.
  3. 最小的連線數: least_conn.
  4. 會話保持策略:
    1. IP會話保持: ip_hash
    2. hash - 指定伺服器組的負載均衡方法,其中客戶機-伺服器對映基於hash 值。key可以包含文字、變數及其組合。

選型過程:

負載均衡策略,根據實際情況按需選擇,無特殊要求的情況下選擇 rr 即可。
會話保持策略, 需要根據特定的場景進行選擇:

  • 不需要會話保持, 則不進行配置.
  • 需要根據源地址進行會話保持: ip_hash
  • 需要進行 cookie 會話保持: sticky
  • 源地址會話保持和 cookie 會話保持均無法滿足需求, 則可能需要透過 hash 來定製會話保持策略.

3.7.3 應用服務層 -> 資料庫層高可用選型

略.

由於應用系統的多樣性, 本文不對應用服務層 -> 資料庫層高可用選型做約束. 僅提供頂層架構要求:

  1. 資料庫: 主從同步, 讀寫分離
  2. 應用:
    1. 實現資料庫連線池功能. 可以配置多個資料庫連線.
    2. 根據應用功能模組的重要性進行橫向拆封. 將: 報表, 資料統計, 批處理類功能與低延遲重要業務功能剝離開來.

參考檔案

參考檔案
Availability - Wikipedia
High Availability - Wikipedia
system-design-primer - GitHub
High Availability Support for NGINX
Usage of web servers broken down by ranking

三人行, 必有我師; 知識共享, 天下為公. 本文由東風微鳴技術部落格 EWhisper.cn 編寫.

相關文章