我們一起聊聊軟件架構(gòu)伸縮性法則
對于大部分商業(yè)和政府部門的系統(tǒng),初始的開發(fā)和部署更側(cè)重于實現(xiàn)功能的可用性和創(chuàng)新性,而不是可伸縮性。在早期階段,只要系統(tǒng)能夠應(yīng)對現(xiàn)有的工作負(fù)載,開發(fā)團(tuán)隊就會優(yōu)先考慮引入新功能以提升業(yè)務(wù)價值。然而,隨著系統(tǒng)的發(fā)展,性能和可伸縮性逐漸成為關(guān)鍵問題,甚至關(guān)乎系統(tǒng)的生存。在這一點上,架構(gòu)師需負(fù)起責(zé)任,將系統(tǒng)改造為能夠快速響應(yīng)并支持伸縮性的架構(gòu)。
成本和伸縮性之間的關(guān)系
對系統(tǒng)進(jìn)行伸縮的一個核心原則是能夠方便地添加新資源來處理增長的負(fù)載。對于很多系統(tǒng)來說,一個簡單而有效的方法是部署多個無狀態(tài)服務(wù)器實例,并使用負(fù)載均衡器在這些實例之間分配請求,如下圖。
圖片
在云平臺部署資源時,成本主要由兩部分構(gòu)成:
一是每個虛擬機(jī)服務(wù)器實例的部署成本
二是負(fù)載均衡器的成本,后者取決于新的和活躍的請求數(shù)量以及處理的數(shù)據(jù)量。隨著請求量的增加,已部署的虛擬機(jī)需要具備更高的處理能力,導(dǎo)致成本上升。
同時,負(fù)載均衡器的費用也會隨著請求和處理的數(shù)據(jù)量的增加而增長。因此,成本的增加與系統(tǒng)規(guī)模的擴(kuò)大是相互影響的,可伸縮性設(shè)計的選擇將不可避免地影響到部署成本。忽略這個因素可能導(dǎo)致意外的高昂費用。
為了控制成本,主要有兩個策略:采用彈性負(fù)載均衡器自動根據(jù)實際請求量調(diào)整服務(wù)器實例的規(guī)模;以及提升每個服務(wù)器實例的處理能力,通常通過優(yōu)化服務(wù)器配置(如線程數(shù)量、連接數(shù)量、堆內(nèi)存大小等)實現(xiàn)。通過精心調(diào)整這些參數(shù),可以顯著提升性能和處理能力,進(jìn)而降低成本。
注意系統(tǒng)瓶頸
對一個系統(tǒng)進(jìn)行伸縮本質(zhì)上就是要增加它的容量。在上面的示例中,我們通過部署更多的服務(wù)器實例來提高請求處理能力。
但是,軟件系統(tǒng)是由多個相互依賴的處理元素或微服務(wù)組成的,所以在增加一部分微服務(wù)容量的同時,不可避免地會被其他一些微服務(wù)拖累。在我們的負(fù)載均衡示例中,假設(shè)服務(wù)器實例都連接到同一個共享數(shù)據(jù)庫。隨著部署服務(wù)器數(shù)量的增加,數(shù)據(jù)庫的請求負(fù)載也隨之增加 (如下圖)。
圖片
達(dá)到一定階段時,數(shù)據(jù)庫性能會成為限制因素,導(dǎo)致訪問速度明顯下降。
這時,即便增加服務(wù)器的處理能力,也無法從根本上解決問題,因為問題出在數(shù)據(jù)庫上。要想實現(xiàn)進(jìn)一步的系統(tǒng)擴(kuò)展,就必須增強(qiáng)數(shù)據(jù)庫的處理能力。這可以通過優(yōu)化查詢語句、增配CPU或內(nèi)存資源、執(zhí)行數(shù)據(jù)庫復(fù)制或分片等多種方式來實現(xiàn)。
當(dāng)然,還有許多其他方法可以緩解這個問題。系統(tǒng)內(nèi)的任何共享資源都可能變成性能瓶頸。在增加系統(tǒng)的某個部分的能力時,必須考慮到對下游部分的影響,避免因增強(qiáng)而引起系統(tǒng)的其他部分突然承受不住壓力,這種情況可能會導(dǎo)致連鎖反應(yīng),進(jìn)而使整個系統(tǒng)崩潰。數(shù)據(jù)庫、消息隊列、網(wǎng)絡(luò)連接的長時間延遲、線程及連接池和共享的微服務(wù)等,都是潛在的性能瓶頸所在。一旦面臨高流量負(fù)載,這些瓶頸點很快就會暴露出來。因此,關(guān)鍵在于一旦瓶頸出現(xiàn),能夠防止系統(tǒng)突然崩潰,并能迅速擴(kuò)展系統(tǒng)能力以應(yīng)對。
慢服務(wù)比故障服務(wù)更有害
在正常情況下,系統(tǒng)應(yīng)該能夠為微服務(wù)和數(shù)據(jù)庫提供穩(wěn)定、低延遲的通信。當(dāng)系統(tǒng)負(fù)載保持在正常的配置水平時,性能是可預(yù)測、一致和快速的,如下圖所示。
圖片
當(dāng)客戶端的請求量超出常規(guī)范圍時,微服務(wù)架構(gòu)中服務(wù)間的請求響應(yīng)時間會開始延長。這尤其明顯當(dāng)進(jìn)入的請求負(fù)荷超過了某個特定服務(wù)(例如服務(wù)B)的處理能力時,這時未處理完的請求就會在前置微服務(wù)(例如服務(wù)A)中累積。因為下游服務(wù)的處理速度減緩,導(dǎo)致這個微服務(wù)接收到的請求量超過了它能夠完成的請求量。
圖片
當(dāng)服務(wù)因為波動或資源耗竭面臨壓力過大而無法正常響應(yīng)客戶端請求時,客戶端會經(jīng)歷延遲,這種情況可能引起連鎖反應(yīng),即級聯(lián)故障——一個響應(yīng)緩慢的服務(wù)導(dǎo)致沿請求鏈路的請求積壓,進(jìn)而可能造成整個系統(tǒng)的崩潰。
為了防止這種級聯(lián)故障,可以采用一些架構(gòu)模式,例如回路斷路器和隔板。回路斷路器在檢測到服務(wù)延遲超過預(yù)設(shè)閾值時,可以自動減少請求流向該服務(wù),或完全切斷對其的請求,以防止系統(tǒng)過載。隔板則通過隔離下游服務(wù)的故障,保護(hù)上游服務(wù)不受影響,從而在一個服務(wù)出現(xiàn)問題時,避免整個系統(tǒng)受損。這些策略有助于構(gòu)建出更加彈性和可擴(kuò)展的系統(tǒng)架構(gòu)。