考慮系統擴展性時僅僅理解AKF立方體是不夠的

圖/蔣坤(一位攝影師程序員)

新技術層出不窮,日新月異。幾乎每年都有熱點,比如去年的區塊鏈,前些年的微服務。

無論再怎麼與時俱進總有變與不變的東西。技術在變,有的思想沒變。

我們今天就是談論些思想沒有變的東西,也是被一直以來實踐檢驗的。那就是我們考慮系統擴展性的時候,我們是如何思考以及去實施的。

說起如何設計一個系統的可擴展性的時候,一般我們首先需要一套理論來指導,另外還需要一些設計原則和注意事項。

那麼AKF立方體無疑是一個比較合適的選擇。

第一次看到AKF立方體的說法是在《架構即未來》一書中,第二次看到是在《微服務架構設計模式》這本書中,其實它還有個更早的出處《可擴展的藝術》,當然本文也有對它們的參考。

一、AKF立方體

立方體,就是一個三維的空間,我們要的是 “可擴展”,那麼沒有比三維的空間更能表達擴展性的了。

AKF立方體是一種理論指導,它可以幫助我們在各個方向上做擴展。X、Y、Z三個方向都給我們指明瞭道路,讓我們在執行的時候可以在不同的方向上做一個參考,參照這一理論來確認我們所做的擴展動作是否符合這一理論。

下圖是一個立方體的展示圖。

X、Y、Z軸的解讀

X軸-橫向擴展、水平復制

Z軸-數據分區,比如分庫分表

Y軸-功能分解擴展,屬於微服務方向

關於AKF更詳細的介紹,大家可以查閱其它相關資料。

這裏我重點說一點,就是我們在理解AKF立方體的時候,注意一下左下角,也就是上圖虛線圓圈的部分。

從這個畫圈地方,一個系統相當於初始狀態,也是最原始的起點單體,單一實例,有待擴展挖掘的狀態。在這種狀態下要尋求擴展,就會向三個方向延伸,也就是我們上面介紹的X、Y、Z三個維度。

鑑於我們這篇文章的題目是,當我們聊系統擴展性的時候不僅僅是AKF立方體,接下來我們重點敘述基於這套理論爲基礎其它的內容。

二、可擴展性、可用性、成本

尋求可擴展性的同時要基於可用性,總不能任性擴展而使系統不可用吧。那麼當擴展性和可用性都有了保障的時候,如果忽視了成本,也是要不得。投入產出要有個正比。

這裏的成本考慮主要是設計的複雜度,AKF立方體確定了三個維度方向的擴展理論,在每一個維度上,都可深,可淺的進行。

比如橫向X軸擴展的時候,我們是否考慮程序設計的是有狀態還是無狀態等等,因爲有狀態和無狀態的兩種設計的成本也是不一樣的,接下來我們還會對狀態設計詳細介紹。

我們在考慮可擴展性的同時一定要將可用性和成本這兩個因素也要考慮進來,他們三者的關係需要做一個平衡,如下圖所示。

三、設計上的一些原則考慮

1、對異步、同步的考慮

同步的系統調用,比如系統A->系統B->系統C,形成一個同步調用鏈,這個調用鏈最大的問題是會發生故障傳導。

同步交互的系統,他們的擴展性會受到同步調用鏈中最慢的那個系統的限制。一旦某個系統或者某個系統的RPC接口變慢,那麼調用鏈靠前的系統都會慢下來,也就是我們上面說的傳導。

當訪問量增大的時候,一請求一線程的模式下,就會拖慢整個調用方的系統。

但異步調用的系統,對這種“慢”的容忍性會更強。因爲如果一旦一個請求依賴變慢,在等待系統響應的同時,可以去處理下一個請求。

雖然響應變慢了,但整個系統並沒有變慢。因爲能夠容忍這種變慢,所以就可以繼續處理其它的請求,因此異步調用的系統相當於“實時的進行了動態的擴展”。

我們應當儘可能將系統的通訊模式設計成異步的,這樣在系統遇到極值負荷的時候,可以有更強的容錯能力,這種容錯能力就是上面提到可以容忍系統調用性能的下降。

有關同步調用的問題鏈更詳細的介紹可參考讓研發人員緊張的這條“故障神經線”(上)

2、對狀態考慮

這裏的狀態是我們一般說的,設計成有狀態的還是設計成無狀態的。最好是設計成無狀態的。

啥叫狀態,我們都知道HTTP通信是無狀態的,請求-響應-結束,不會關心上下文,因爲每次發送HTTP請求的時候不需要知道上一次發送的是什麼內容。

那麼,可能你會說,使用了cookie或者session,也保存了用戶的會話信息。但這是藉助了外力,HTTP本身就是無狀態的通訊,這樣非常簡單。

根據AKF立方體的指導理論,我們沿X軸橫向擴展。在這之前,我們只有一臺WEB服務器,用戶登錄會話信息都可以保留在這一臺服務器上面。

那麼,橫向擴展到幾臺WEB服務器共存的時候,你就需要考慮會話信息同步了,因爲下一次的請求不一定會落在上一次請求的服務器上面。

當然解決的方法有很多,比如將會話保存在客戶端,再者使用分佈式緩存來保存,總之你需要多一份考慮。

如果我們沿Y軸擴展,做分庫分表操作,那麼問題也來了,對於所有用戶的數據應該如何存放,一般我們是按照用戶的USERID屬性來做路由,這樣用戶的數據會分散到不同的分庫或分表上面。

這樣我們的應用程序在接收用戶的數據請求的時候就需要多處理一層邏輯,需要根據USERID來匹配對於的分庫分表,也需要多一份考慮。

因此,在實踐了AKF之後,這些都是需要我們從設計上需要仔細考慮的。

擴展性的設計原則,當然不止上面兩條,還有比如可監控的設計、多站點設計等等,本文結合我自己的親身經歷,特意選了通信方式和狀態設計這兩個來闡述。

四、故障

我們不能只專注於系統的擴展性而忽略了系統的故障風險,不然,到頭來就是 “竹籃子打水一場空”,因爲擴展性再好,系統漏洞百出,系統的使用者不能得到任何體驗。

其中“復發的故障”便是擴展性的最大阻礙,每當生產環境中因同樣的故障而造成的系統不可用,這種故障相當於盜竊了我們研發人員的時間和精力,因爲它是一種重複的故障。

而我們追求的擴展性的原則就是用較少的成本來維護系統承接需求的能力,那麼復發的故障就與這一原則相悖了。

我們如何來測量一個系統發生故障的可能性呢,在按照AKF實施了以後,比如Y軸擴展,把一個龐雜的系統按照功能去拆分,那麼我們的一個系統所依賴的系統就會增多,這也是微服務的特點之一。

在微服務的環境下有好多個小而自治的系統存在。隨着一個系統所依賴系統的增多,這個系統發生故障的機率也會增大。大致有如下這樣的一個計算公式,我們以API GATEWAY系統爲例。

從統計意義上講,一個系統操作的可用性,由它所依賴的所有的服務共同決定。比如API GATEWAY 所依賴的服務1、服務2、服務3的可用性都是99.5%,那麼API GATEWAY的可用性就是99.5% * 99.5% * 99.5% = 98.5%。

每一個額外的服務參與到其中,都會進一步降低API GATEWAY 的整體可用性。

五、總結

在軟件領域一定是先有了動作,大家或者越來越多的人已經那樣去做了,只是此時還沒有人,沒有那麼一個牛人給抽象出來,一旦抽象出來之後,就有了概念。分佈式、微服務、種種設計模式都是這樣,AKF立方體也是這樣。

我們什麼時候進行X軸擴展,什麼時候進行Y軸擴展,又在什麼時候進行Z軸擴展呢。

一般情況下,交易量高、數據需求低、讀多寫少的系統,最經濟的做法是採取X軸擴展最經濟的原因是這種方式,只是應用層的簡單複製。

而對於那些用戶數據增長較快,功能的複雜度增長也較快的系統,我們就需要考慮三個維度的擴展。

我的建議是在設計一個系統當初的時候三個維度就應該都需要有所考慮,這樣當需求增長迅猛的時候我們可以快速擴展來滿足用戶的需求。

後記

說點題外話,也是大實話,我在京東的這些年,最惱人的是半夜凌晨收到報警打擾睡眠,週末休息時又被報警阻斷了生活節奏。

有兩種選擇,選擇一是離開它,選擇二是戰勝它。因此我無時無刻不在考慮如何保障平臺生產的穩定性和擴展性。

所以我寫的內容基本都是基於我工作的生產環境,有時候爲了公司生產的保密性,然後在這個基礎之上做了抽象總結。

希望每一篇文章對大家都能有所幫助。

往期文章

《寫給關注我的你們》

發佈了87 篇原創文章 · 獲贊 30 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章