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