聊聊軟件架構(gòu)伸縮性的三大法則
對于大多數(shù)商業(yè)和政府系統(tǒng)而言,在開發(fā)與部署的初期,可伸縮性并非首要需求,可用性以及實用的新功能才是開發(fā)周期的主要推動因素。只要系統(tǒng)能夠滿足正常負載,便會持續(xù)添加新功能以提升系統(tǒng)的業(yè)務(wù)價值。然而,當系統(tǒng)發(fā)展到一定階段時,性能和可伸縮性會成為緊迫問題,甚至關(guān)乎系統(tǒng)的生存。在這種情況下,架構(gòu)師有責任將系統(tǒng)演變?yōu)橐粋€響應(yīng)迅速且可伸縮的系統(tǒng)。
成本和伸縮性之間的關(guān)系
系統(tǒng)進行伸縮的核心原則之一是能夠便捷地增添新資源以應(yīng)對增長的負載。就許多系統(tǒng)來說,一種簡單且有效的方法是部署多個無狀態(tài)服務(wù)器實例,并利用負載均衡器在這些實例之間分配請求,如下圖所示。
圖片
倘若這些資源部署在云平臺上,其成本包括:每個服務(wù)器實例的虛擬機部署成本,以及由新請求和活躍請求的數(shù)量、所處理的數(shù)據(jù)量決定的負載均衡器成本。
在此場景中,隨著請求負載的增加,已部署的虛擬機需具備更大的處理能力,這便導致了更高的成本。同時,負載均衡器的開銷也會隨請求負載和數(shù)據(jù)大小成比例增長。所以,成本與規(guī)模相互關(guān)聯(lián),可伸縮性的設(shè)計決策必然會影響部署成本。若忽視這一點,可能會收到意想不到的巨額部署賬單。
那么,該如何降低成本呢?主要有兩種方式。其一,使用彈性負載均衡器,依據(jù)實時請求負載來調(diào)整服務(wù)器實例的數(shù)量。其二,增加每個服務(wù)器實例的容量,這通常是通過調(diào)整服務(wù)器部署參數(shù)(如線程數(shù)、連接數(shù)、堆大小等)來實現(xiàn)。精心選擇參數(shù)設(shè)置能夠顯著提升性能,進而提高容量。
注意系統(tǒng)瓶頸
對一個系統(tǒng)進行伸縮,本質(zhì)上是要提升它的容量。在上述示例中,我們通過部署更多的服務(wù)器實例來增強請求處理能力。然而,軟件系統(tǒng)是由多個相互依存的處理元素或微服務(wù)構(gòu)成的,所以在增加一部分微服務(wù)容量時,不可避免地會受到其他一些微服務(wù)的牽制。在我們的負載均衡示例里,假設(shè)服務(wù)器實例都連接至同一個共享數(shù)據(jù)庫。隨著部署的服務(wù)器數(shù)量增多,數(shù)據(jù)庫的請求負載也隨之增加(如下圖)。
圖片
在某個階段,數(shù)據(jù)庫會達到飽和狀態(tài),數(shù)據(jù)庫訪問將開始出現(xiàn)較大的延遲。此時,數(shù)據(jù)庫成為瓶頸 —— 即便增加更多的服務(wù)器處理能力也于事無補。若要進一步進行伸縮,就需要以某種方式增加數(shù)據(jù)庫的容量??梢試L試優(yōu)化查詢,或者增添更多的 CPU 或內(nèi)存,也可以對數(shù)據(jù)庫進行復制或分片。除此之外,還有許多其他解決方案。系統(tǒng)中的共享資源都有可能成為瓶頸。
當在架構(gòu)的某些部分增加容量時,需要仔細考量下游的容量,確保不會突然對系統(tǒng)造成沖擊。因為這樣會迅速引發(fā)級聯(lián)故障(參見下一條規(guī)則),并致使整個系統(tǒng)崩潰。數(shù)據(jù)庫、消息隊列、長延遲網(wǎng)絡(luò)連接、線程和連接池以及共享微服務(wù)都是潛在的瓶頸??梢钥隙ǖ氖?,高流量負載會很快使這些瓶頸顯露出來。關(guān)鍵在于當瓶頸暴露時,能夠防止系統(tǒng)突然崩潰,并迅速部署更多的能力。
慢服務(wù)比故障服務(wù)更有害
在正常情況下,系統(tǒng)應(yīng)當能夠為微服務(wù)和數(shù)據(jù)庫提供穩(wěn)定且低延遲的通信。當系統(tǒng)負載處于正常的配置水平時,性能是可預測、一致且快速的,如下圖所示。
圖片
一旦客戶端負載超出正常水平,微服務(wù)之間的請求延遲便會開始增加。特別是在傳入的請求負載持續(xù)超過容量(如服務(wù) B)的情況下,未完成的請求會在微服務(wù) A 中堆積,由于下游延遲變慢,該微服務(wù)此時接收的請求比已完成的請求更多。
圖片
當一個服務(wù)因抖動或資源耗盡而不堪重負時,服務(wù)將無法響應(yīng)客戶端,客戶端也會陷入停滯狀態(tài)。其直接結(jié)果就是級聯(lián)故障 —— 緩慢的服務(wù)會致使請求沿著請求路徑不斷累積,直至整個系統(tǒng)崩潰。一些架構(gòu)模式(如回路斷路器和隔板)可用于防止級聯(lián)故障。若服務(wù)的延遲超過指定值,斷路器會調(diào)節(jié)請求負載,甚至將其斷開。當僅有一個下游依賴項發(fā)生故障時,隔板能夠保護上游的微服務(wù)不發(fā)生故障。這些措施可用于構(gòu)建具有彈性且高度可伸縮的架構(gòu)。