我們生活在一個時代,大規(guī)模的,面向互聯(lián)網(wǎng)的系統(tǒng)(例如Google,Amazon,F(xiàn)acebook等)是工程界的偶像。 他們每秒處理大量請求,并管理規(guī)??涨暗臄?shù)據(jù)存儲庫。 出于商業(yè)秘密的原因,在這些系統(tǒng)上獲取準確的流量數(shù)字并不容易。 但是,這些站點隨著使用量的增長而迅速擴展的能力是其持續(xù)成功的關鍵因素。
幸運的是,我們可以通過一家技術公司的年度使用情況報告深入了解以Internet規(guī)模處理的請求和數(shù)據(jù)量。 從2019年起,您可以在此瀏覽其令人難以置信的詳細使用情況統(tǒng)計信息。這是對大規(guī)模系統(tǒng)功能的令人著迷的一瞥。 不過請注意,這是Pornhub.com。 該報告不適合該報告。 以下是PG-13的一個示例性數(shù)據(jù)點-他們在2019年有420億的訪問量!
對于絕大多數(shù)企業(yè)和政府系統(tǒng)而言,可擴展性并不是開發(fā)和部署初期的主要質(zhì)量要求。 增強可用性和實用性的新功能是我們開發(fā)周期的驅(qū)動力。 只要正常負載下的性能足夠,我們就會繼續(xù)添加面向用戶的功能,以提高系統(tǒng)的業(yè)務價值。
盡管如此,系統(tǒng)發(fā)展成為一種狀態(tài),在這種狀態(tài)下,增強的性能和可伸縮性變得迫在眉睫,甚至是生存,這并不少見。 引人注目的功能和高實用性催生了成功,這帶來了更多的處理請求和更多的數(shù)據(jù)管理。 這通常預示著一個臨界點,在輕載下有意義的設計決策現(xiàn)在突然變成了技術負擔。 外部觸發(fā)事件通常會導致這些轉(zhuǎn)折點-在2020年3月的媒體上,許多報道稱政府失業(yè)和超市在線訂購網(wǎng)站由于冠狀病毒大流行而在需求下崩潰。
當達到這個臨界點時,架構師有責任帶領系統(tǒng)演進為高響應,可擴展的系統(tǒng)。 核心系統(tǒng)的架構機制和模式將需要重新設計,以使其能夠應對不斷增長的需求。 對于許多架構師而言,這是未知的或陌生的領域,因為可伸縮性使我們走下了有時對于廣泛理解的軟件體系結(jié)構原理而言異端的道路。
以下六個經(jīng)驗法則代表著每位軟件架構師必須幫助他們構建可伸縮系統(tǒng)的知識。 這些通用規(guī)則可以為架構師在可靠地處理不斷增長的請求負載和數(shù)據(jù)量的過程中提供指導。
成本和可擴展性有著不可磨滅的聯(lián)系
擴展系統(tǒng)的核心原則是能夠輕松添加新的處理資源來處理增加的負載。 對于許多系統(tǒng),一種簡單有效的方法是部署多個無狀態(tài)服務器資源實例,并使用負載平衡器在這些實例之間分配請求(請參見圖1)。 假設將這些資源部署在Amazon Web Services之類的云平臺上,則基本費用為:
· 每個服務器實例的虛擬機部署成本
· 負載均衡器的成本,取決于新請求和活動請求的數(shù)量以及處理的數(shù)據(jù)量
在這種情況下,隨著請求負載的增長,就需要運行服務器代碼的已部署虛擬機具有更大的處理能力。 這導致更高的成本。 您的負載均衡器成本還將與您的請求負載和數(shù)據(jù)大小成比例地增長。
> Figure 1 A Simple Load Balancing Example
因此,成本和規(guī)模是并存的。 您關于可伸縮性的設計決策不可避免地會影響您的部署成本。 忘記了這一點,您可能會發(fā)現(xiàn)自己以及許多知名公司在一個月底收到了意外大筆的部署費用!
在這種情況下,您的設計如何降低成本? 主要有兩種方法:
· 使用彈性負載平衡器可根據(jù)瞬時請求負載來調(diào)整服務器實例的數(shù)量。 然后,在交通繁忙期間,您需要為最少數(shù)量的服務器實例付費。 隨著請求量的增長,負載均衡器會產(chǎn)生新的實例,并且容量也會相應地增長。
· 增加每個服務器實例的容量。 這通常是通過調(diào)整服務器部署參數(shù)(例如線程數(shù),連接數(shù),堆大小等)來完成的。 默認平臺設置很少適合您的工作負載。 仔細選擇參數(shù)設置可以顯著提高性能,從而提高容量。 您基本上是在使用相同的資源來完成更多工作-這是實現(xiàn)擴展的關鍵原則。
您的系統(tǒng)存在瓶頸。 某處!
擴展系統(tǒng)實質(zhì)上意味著增加其容量。 在上面的示例中,我們通過在負載平衡的計算資源上部署更多服務器實例來提高請求處理能力。 但是,軟件系統(tǒng)包括多個從屬處理元素或微服務。 不可避免地,隨著某些微服務中容量的增加,您將淹沒其他微服務中的容量。
在我們的負載均衡示例中,假設我們的服務器實例均具有到同一共享數(shù)據(jù)庫的連接。 隨著部署服務器數(shù)量的增加,我們增加了數(shù)據(jù)庫上的請求負載(請參見圖2)。 在某個階段,此數(shù)據(jù)庫將達到飽和,并且數(shù)據(jù)庫訪問將開始引起更多的延遲。 現(xiàn)在,您的數(shù)據(jù)庫已成為瓶頸,無論您增加更多的服務器處理能力都無所謂。 為了進一步擴展,解決方案是以某種方式增加數(shù)據(jù)庫容量。 您可以嘗試優(yōu)化查詢,或添加更多的CPU和/或內(nèi)存。 也許復制和/或分片數(shù)據(jù)庫。 有很多可能性。
> Figure 2 Increasing Server Capacity creates a Bottleneck at the Database
系統(tǒng)中的任何共享資源都可能成為限制容量的瓶頸。 當您增加部分架構的容量時,您需要仔細查看下游的容量,以確保不會因請求突然而意外地淹沒您的系統(tǒng)。 這會迅速導致級聯(lián)故障(請參閱下一條規(guī)則),并使整個系統(tǒng)崩潰。
數(shù)據(jù)庫,消息隊列,長時間等待的網(wǎng)絡連接,線程和連接池以及共享的微服務都是瓶頸的主要候選者。 您可以放心,高流量負載將迅速暴露這些元素。 關鍵是防止瓶頸暴露時突然崩潰,并能夠快速部署更多容量。
慢服務比失敗服務更邪惡
在正常操作下,系統(tǒng)應設計為在微服務和組成系統(tǒng)的數(shù)據(jù)庫之間提供穩(wěn)定,低延遲的通信。 盡管系統(tǒng)負載保持在您設計的運行配置文件之內(nèi),但性能仍然是可預測的,一致且快速的,如圖3所示。
> Figure 3 Low latencies under normal load
隨著客戶端負載增加到超出操作配置文件的范圍,微服務之間的請求等待時間將開始增加。 首先,這通常是一個緩慢而穩(wěn)定的增長,可能不會嚴重影響整個系統(tǒng)的運行,尤其是在負載激增短暫的情況下。 但是,如果傳入請求負載繼續(xù)超過容量(服務B),則未完成的請求將開始備份在發(fā)出請求的微服務(服務A)中,由于下游等待時間較慢,該服務現(xiàn)在看到的傳入請求多于已完成的請求。 如圖4所示。
> Figure 4 Increased load causes longer latencies and requests to back up
在這種情況下,事情可能真的會迅速消退。 當一項服務不堪重負,并且由于顛簸或資源耗盡而基本停止運行時,請求的服務將無法響應其客戶,而客戶也將停止運行。 導致的結(jié)果稱為級聯(lián)故障-緩慢的微服務導致請求沿著請求處理路徑建立,直到整個系統(tǒng)突然出現(xiàn)故障。
這就是為什么緩慢的服務是邪惡的,而不是不可用的服務更是如此。 如果您呼叫失敗的服務或由于瞬態(tài)網(wǎng)絡問題而進行了分區(qū)的服務,則您會立即收到異常消息,并可以明智地決定做什么(例如退避并重試,報告錯誤)。 逐漸不堪重負的服務正常運行,只是延遲時間更長。 這暴露了所有依賴服務中的潛在瓶頸,最終,出了一些大問題。
斷路器和隔板等架構模式可防止級聯(lián)故障。 如果對服務的延遲超過指定值,則斷路器可以限制請求負載或釋放請求負載。 如果只有一個下游服務依賴項失敗,則隔板可以保護整個微服務免于失敗。 使用它們來構建彈性以及高度可擴展的體系結(jié)構。
數(shù)據(jù)層最難擴展
核心業(yè)務數(shù)據(jù)示例是客戶資料,交易和帳戶余額。 這些必須正確,一致且可用。
操作數(shù)據(jù)示例包括用戶會話時長,每小時訪問者和頁面瀏覽量。 該數(shù)據(jù)通常具有保存期限,并且可以隨時間進行匯總和匯總。 如果還不是100%完成,那就不是世界末日。 因此,我們可以更輕松地捕獲和存儲帶外操作數(shù)據(jù),例如將其寫入日志文件或消息隊列。 消費者然后定期檢索數(shù)據(jù)并將其寫入數(shù)據(jù)存儲。
隨著系統(tǒng)請求處理層的擴展,共享事務數(shù)據(jù)庫將承受更多負載。 隨著查詢負載的增加,這些可能迅速成為瓶頸。 查詢優(yōu)化是一個有用的第一步,添加更多內(nèi)存以使數(shù)據(jù)庫引擎能夠緩存索引和表數(shù)據(jù)也是如此。 最終,您的數(shù)據(jù)庫引擎將耗盡所有精力,并且需要進行更根本的更改。
首先要注意的是,任何數(shù)據(jù)組織的更改都可能在數(shù)據(jù)層帶來痛苦。 如果更改關系數(shù)據(jù)庫中的架構,則可能必須運行腳本以重新加載數(shù)據(jù)以匹配新架構。 在腳本運行期間(對于大型數(shù)據(jù)庫而言可能是很長的時間),系統(tǒng)無法進行寫入。 這可能不會使您的客戶滿意。
NoSQL,無模式數(shù)據(jù)庫減輕了重新加載數(shù)據(jù)庫的需要,但是您仍然必須更改查詢級代碼才能識別已修改的數(shù)據(jù)組織。 如果您擁有業(yè)務數(shù)據(jù)集合,其中某些項目的格式已修改,而某些項目的原始格式已修改,則可能還需要管理數(shù)據(jù)對象的版本控制。
進一步擴展可能需要分發(fā)數(shù)據(jù)庫。 帶有只讀副本的領導者追隨者模型可能就足夠了。 對于大多數(shù)數(shù)據(jù)庫來說,這很容易設置,但是需要密切的持續(xù)監(jiān)視。 領導者死亡時,故障轉(zhuǎn)移很少是瞬時的,有時需要手動干預。 這些問題都是非常依賴數(shù)據(jù)庫引擎的。
如果采用無領導者方法,則必須決定如何最好地在多個節(jié)點之間分配和分區(qū)數(shù)據(jù)。 在大多數(shù)數(shù)據(jù)庫中,一旦選擇了分區(qū)鍵,就無法在不重建數(shù)據(jù)庫的情況下進行更改。 不用說,分區(qū)鍵需要明智地選擇! 分區(qū)鍵還控制如何在節(jié)點之間分配數(shù)據(jù)。 隨著添加節(jié)點以提供更大的容量,需要進行重新平衡以在新節(jié)點上分布數(shù)據(jù)和請求。 同樣,數(shù)據(jù)庫文檔的內(nèi)容中描述了它的工作方式。 有時它并不像它可能的那樣平滑。
由于分布式數(shù)據(jù)庫的潛在管理難題,基于托管的基于云的替代方案(例如AWS Dynamodb,Google Firestore)通常是首選。 當然,需要權衡取舍-這是另一個故事的主題!
這里的信息很簡單。 更改邏輯和物理數(shù)據(jù)模型以擴展查詢處理能力很少是一個平穩(wěn)而簡單的過程。 想要不經(jīng)常面對的人。
快?。?快?。?并緩存更多!
減輕數(shù)據(jù)庫負載的一種方法是避免盡可能訪問它。 這就是緩存的用處。您友好的數(shù)據(jù)庫引擎應該能夠充分利用節(jié)點緩存上的資源。 這是一個簡單且有用的解決方案,如果可能會很昂貴。
更好的是,如果不需要,為什么還要查詢數(shù)據(jù)庫? 對于經(jīng)常讀取且很少更改的數(shù)據(jù),可以修改您的處理邏輯以首先檢查分布式緩存,例如memcached服務器。 這需要遠程調(diào)用,但是如果您需要的數(shù)據(jù)在高速緩存中,則在快速網(wǎng)絡上,這比查詢數(shù)據(jù)庫實例要便宜得多。
引入緩存層需要修改您的處理邏輯,以檢查緩存數(shù)據(jù)。 如果所需的內(nèi)容不在高速緩存中,則您的代碼仍必須查詢數(shù)據(jù)庫,然后將結(jié)果加載到高速緩存中并將其返回給調(diào)用方。 您還需要決定何時刪除或使緩存的結(jié)果無效-這取決于您的應用程序向客戶提供陳舊結(jié)果的容忍度。
設計良好的緩存方案對于擴展系統(tǒng)絕對是無價的。 如果您可以處理來自緩存的大部分讀取請求,則可以在數(shù)據(jù)庫上購買額外的容量,因為它們不參與處理大多數(shù)請求。 這意味著您可以避免復雜且痛苦的數(shù)據(jù)層修改(請參閱上一條規(guī)則),同時為越來越多的請求創(chuàng)建容量。 這是使大家開心的秘訣! 甚至會計師。
監(jiān)控是可伸縮系統(tǒng)的基礎
這是很多工作。 而且很難使所有事物都代表現(xiàn)實,因此您可以獲得有意義的結(jié)果。 毫不奇怪,它很少完成。
替代方法是監(jiān)視。 對系統(tǒng)的簡單監(jiān)視涉及確?;A結(jié)構正常運行。 如果資源不足,例如內(nèi)存或磁盤空間不足,或者遠程調(diào)用失敗,則應向您發(fā)出警報,以便在真正的不良情況發(fā)生之前可以采取補救措施。
以上監(jiān)視見解是必要的,但不足。 隨著系統(tǒng)的擴展,您需要了解應用程序行為之間的關系。 一個簡單的示例是,隨著并發(fā)寫入請求數(shù)量的增加,數(shù)據(jù)庫的寫入性能如何。 您還想知道何時由于下游延遲增加而使斷路器在微服務中跳閘,負載平衡器何時開始產(chǎn)生新實例或消息在隊列中保留的時間超過指定的閾值。
有許多可用于監(jiān)視的解決方案。 Splunk是一個全面而強大的日志聚合框架。 任何云都有其自己的監(jiān)視框架,例如AWS Cloudwatch。 這些功能使您可以捕獲有關系統(tǒng)行為的指標,并將其顯示在統(tǒng)一的儀表板中,以支持對性能的監(jiān)視和分析。 術語"可觀察性"通常用于涵蓋監(jiān)視和性能分析的整個過程。
有兩件事(至少?。┮紤]。
首先,要獲得對性能的深入了解,您將需要生成與應用程序行為細節(jié)相關的自定義指標。 仔細設計這些指標,并在您的微服務中添加代碼以將其注入到您的監(jiān)視框架中,以便可以在系統(tǒng)儀表板中對其進行觀察和分析。
其次,監(jiān)視是系統(tǒng)中的必要功能(和成本)。 它已打開。 總是。 當您需要調(diào)整性能和擴展系統(tǒng)時,捕獲的數(shù)據(jù)將指導您的實驗和工作。 在系統(tǒng)演進中以數(shù)據(jù)為驅(qū)動力有助于確保您花費時間修改和改進系統(tǒng)部分,這些部分對于支持性能和擴展要求至關重要。
結(jié)論
高性能和可伸縮性通常不是我們構建的許多系統(tǒng)的優(yōu)先質(zhì)量要求。 通常,了解,實施和發(fā)展功能需求是很成問題的,以致浪費所有可用的時間和預算。 但是有時,在外部事件或意外成功的驅(qū)動下,可伸縮性是必要的,否則您的系統(tǒng)將因負載不足而崩潰。 不可用的系統(tǒng)(或由于性能降低而實際上不可用)對任何人都沒有用。
-
互聯(lián)網(wǎng)
+關注
關注
55文章
11251瀏覽量
106451 -
軟件架構
+關注
關注
0文章
64瀏覽量
10499
發(fā)布評論請先 登錄
DPU核心技術論文再次登陸體系結(jié)構領域旗艦期刊《IEEE Transactions on Computers》

睿創(chuàng)微納AI芯片技術登上國際計算機體系結(jié)構領域頂級會議
關于功率模塊冷卻的六個常見問題

函數(shù)指針的六個常見應用場景

AFE5801 fclkin只能輸入只列出了65、50、40、30、20、10MHz這六個值嗎?
ADS805E的轉(zhuǎn)換結(jié)果要延后六個采樣周期才輸出嗎?
【「RISC-V體系結(jié)構編程與實踐」閱讀體驗】-- SBI及NEMU環(huán)境
【「RISC-V體系結(jié)構編程與實踐」閱讀體驗】-- 前言與開篇
焊接機器人六個軸分別是什么作用

無刷DC門驅(qū)動系統(tǒng)的體系結(jié)構

名單公布!【書籍評測活動NO.45】RISC-V體系結(jié)構編程與實踐(第二版)
嵌入式系統(tǒng)的體系結(jié)構包括哪些
DCS分散控制系統(tǒng)的硬件體系結(jié)構介紹

DCS的硬件體系結(jié)構

評論