大規模系統設計模式和原則
如今即使是小公司也可能面臨處理 TB 級的數據或構建每分鐘要處理成千上萬個事件的系統。談到 “大規模”,通常我們指的是系統需要在短時間內處理大量的請求、數據或事件。
如果沒有經過合理設計試圖實現大規模系統註定是失敗的或者代價會很高。本文介紹一些常用的設計原則和模式來實現大規模系統。當我們提到大規模一般都是分佈式系統,我們會從三個方面來說明系統有多好或者多穩定:
-
可用性:系統必須高可用。系統正常運行時間比例是用戶體驗的關鍵,那種沒人能使用的系統就更不用說了。可用性一般使用 “多少個 9” 來衡量。
-
性能:一個系統即使在高負載下也應該能工作和執行任務。而且,處理速度對用戶體驗非常重要;事實表明,這是防止用戶流失的最重要因素之一!
-
可靠性:系統應該準確地處理數據並返回正確的結果。可靠的系統不會無故地失敗、返回不正確的結果或創建損壞的數據。可靠的系統架構是盡力避免故障,當出現故障時,它將檢測、報告,甚至嘗試自動修復故障。
我們可以通過兩種方式擴展系統: -
垂直擴展 (scale-up):將系統部署到性能更高的服務器,CPU、內存配置都更高。
-
水平擴展 (scale-out):將系統部署到更多的服務器上,即創建更多的虛擬機或容器來處理大規模請求、數據或事件。
垂直擴展一般不太接受,有兩個原因: -
系統需要停機部署
-
單個服務器性能存在極限。
另一方面,爲了能夠水平擴展,必須滿足一定條件。例如,系統必須無狀態。(大多數的數據庫不支持直接水平擴展)。
本文的目的是讓您瞭解一些不同的設計模式和原則,使系統能夠向外擴展,同時保持可靠性和彈性。限於篇幅不深入探討每一個主題,只提供一個概述。在每個主題中,會添加有用的鏈接,可以獲得有關該主題的更全面的內容。
下面開始吧!
冪等性
冪等這個術語來自數學,定義如下:
f(f(x)) = f(x)
乍一看可能有點嚇人,但它背後的邏輯很簡單:不管我們對參數 x 調用函數 f 多少次,都會得到相同的結果。這個屬性爲系統提供了極大的穩定性,因爲它允許我們簡化代碼,也使我們的操作更容易:失敗的 HTTP 請求可以重試,崩潰的進程可以重新啓動,而不用擔心副作用。
此外,一個長時間運行的任務可以被分解成多個部分,每個部分本身可以是冪等的,這意味着,當任務崩潰並重新啓動時,所有已經執行的部分將被跳過 (可恢復性)。
異步
當我們進行同步調用時,執行路徑將被阻塞,直到返回響應。這種阻塞有資源開銷,主要是內存和上下文切換的開銷。當可以使系統更高效時,我們就使用異步調用來設計系統。
健康檢查
這種模式是特定於微服務的:每個服務都應該實現一個 / health 接口,在系統正常運行後快速返回。假設一切正常,請求應該返回 HTTP 200,如果服務出現故障,應該返回 500 內部錯誤。當前,我們知道一些錯誤不會被健康檢查發現,但是假設一個系統在高負載情況下響應很慢,也會被健康檢查反映出來,請求會變得遲鈍,這也可以幫助我們識別出問題,並自動生成一個警報,等待運維人員處理。我們也可以選擇暫時將節點從隊列中移除 (請參閱下面的服務發現),直到它再次穩定下來。
斷路器
斷路器是一個從電力領域借用的術語:當電路閉合時,電流流動,當電路打開時,電流停止。
當一個依賴服務不可用時,所有的請求都將失敗。根據快速失敗原則,我們希望請求快速失敗而不是等待直到超時。這也就是斷路器的使用場景:通過封裝一個帶有斷路器的函數調用,斷路器將識別調用一個特定的服務 (例如一個特定的 IP) 是否會失敗,如果會失敗的話,就直接返回調用失敗,而不會真正地執行依賴調用。
斷路器會維持一個狀態 (open/close),並通過定期調用依賴服務來刷新狀態。Netflix 的 Hystrix 庫是一個被廣泛使用的斷路器實現,如今在其他庫中也很常見。
服務發現
在微服務的動態世界中,虛擬機 / 容器經常刪除重建,我們需要一種方法來知道新節點何時加入或刪除。服務發現(也稱爲服務註冊)能解決這個問題,讓每個節點都向一箇中心服務註冊,類似黃頁。這樣,當服務 B 想要調用服務 A 時,它將首先調用服務發現來請求可用節點 (ip) 列表,它將緩存這些節點並使用一段時間。
超時、睡眠和重試
任何網絡都可能出現短暫的錯誤、延遲和擁塞問題。當服務 A 調用服務 B 時,請求可能會失敗,如果發起重試,第二次請求可能會成功。也就是說,重要的是不要以一種傻瓜式 (循環) 實現重試,而要在 reties 之間 “設置” 延遲機制(也稱爲“睡眠”)。原因是我們應該注意被調用的服務,可能有多個其他服務同時調用服務 B,如果所有這些服務都繼續重試,結果將是“重試風暴”,服務 B 將被請求轟炸,這些請求可能會壓垮它,使服務 B 崩潰。爲了避免“重試風暴”,通常的做法是使用指數後退重試機制,這將在重試之間引入指數增長的延遲,並最終導致“超時”,從而阻止任何過多的重試。
降級
有時我們只是需要一個 “B 計劃”。假設我們正在使用推薦服務,以便爲客戶提供最好、最準確的推薦。但是,當服務宕機或短時間內無法訪問時,我們能做什麼呢?
我們可以有另一個服務作爲後備:該服務可以保存我們所有客戶的推薦快照,每週刷新,當它被調用時,它所需要做的就是返回特定客戶的相關快照數據。這種快照是靜態的很容易保存。這些快照可能有點過時,儘管不是最新的建議總比什麼都沒有要好得多。
優秀的工程師在構建系統的時候會考慮這些選項!請注意,斷路器實現可能包括一個服務降級功能!
指標、監控和告警
限流
限流是另一個有用的模式,有助於減少來自系統的壓力。有 3 種限流方式:
-
客戶端限流: https://cloud.google.com/architecture/rate-limiting-strategies-techniques#client-side_strategies
-
服務端限流: https://cloud.google.com/architecture/rate-limiting-strategies-techniques#techniques-enforcing-rate-limits
-
地理位置限流: https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-geo-match.html
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/pr5oPwCZAo1Dh_1OdsxUQQ