從零開始學架構V2-架構設計流程-2

一、架構設計流程

架構的設計的是爲了降低整體的複雜性,那麼架構設計的第一步就是熟悉業務,識別其中的核心訴求,僅考慮技術的話就是識別複雜度。

1.1 識別複雜度

架構的複雜度主要來源於第一節中介紹的“高性能”“高可用”“可擴展”等幾個方面,實際業務中大部分場景我們只會遇到一個”複雜度“,直接對該”複雜度“做整體方案設計、評估、決策、詳細方案設計、落地等步驟做實際落地工作即可;

如果運氣不好,接手涉及多個”複雜度“的系統,那應該怎麼辦呢?答案是先檢查下”識別複雜度“工作是否有問題,大多數業務場景對系統的要求並不高,當識別出多個”複雜度“時,先檢查是否”識別過度“了;當確定有很多個”複雜度“時,先對”複雜度“迫切解決程度排序,優先解決當前面臨的最主要的複雜度問題。一次架構設計不需要一次性解決太多問題,否則很容易遇到以下問題:

  1. 要解決的問題太多,反而不知道從何處着手。
  2. 設計方案本身太複雜,落地時間遙遙無期。
  3. 有些複雜度會使得架構設計點互相矛盾,在設計、評估階段花費大量時間來討論該使用哪種方案。例如,要保護用戶隱私需要對用戶敏感信息進行加密,不同數據加密後的密文完全不同,使得無法直接對該字段模糊搜索,但業務又有搜索需求,此時安全性與系統性能就互相矛盾了。

1.2 整體方案設計

複雜度識別完畢後,接下來將識別出的複雜度作爲做整體方案的要求進行設計。

大多數的架構設計都是借鑑前人優秀架構設計,進行組合、改進演進而來的;從0到1的創新架構設計常常出現在新的技術領域。但這並不意味着架構設計是一個非常簡單的事情,當架構設計方式有很多種時,其組合數量也成幾何式增長,在大多數場景下,簡單的組合並不能滿足需求,還需要稍加改進,因此架構設計並不是一個容易的事情。

下面介紹下架構設計的注意事項:

  1. 架構設計需要符合三個原則:簡單原則、合適原則、演進原則。
  2. 方案中涉及的技術不應該侷限在自己熟悉的技術。可能是之前的架構設計已經驗證過是可靠的,或是其他原因,很多架構師可能不自覺就使用自己已經熟悉的技術,對於新的技術有一種不放心的感覺;當在整體技術方案使用不熟悉的技術時,不僅需要調研該技術是否適合需求,還需要調研該技術性能、學習成本、常見的坑、維護成本、社區活躍程度等。
  3. 在出整體的架構設計時,不應該只有一個方案,3-5個爲宜。太少可能是知識儲備不夠,也可能是視野狹隘;太多則浪費時間;
  4. 每個方案之間的差異應該比較明顯,例如方案一數據存儲使用Mysql、方案二數據存儲使用Oracle,這種差異就不明顯,如果方案二數據存儲使用ES差異就比較明顯了。
  5. 整體方案只需要覆蓋整體思路、關鍵流程,不應在細枝末葉花費太多筆墨。

在編寫整體方式時,使用簡單易理解的圖來幫助說明設計思路,一圖勝千言不無道理;不過切記爲了秀技術而把簡單的問題使用很複雜的圖形表達出來,技術人都一個”秀肌肉“的心理,非常能理解,但謙虛低調往往更容易引來迷弟/妹,比如我,快來波關注吧<手動狗頭>,哈哈。

1.3 評估和選擇方案

整體方案出來後,接下里需要拉會溝通討論選擇哪個方案合適,爲啥一定要拉會呢?本質是降低後期返工的概率,架構師再厲害也會百密一疏,集思廣益不僅縮小思維盲區,還可以避免個人偏見而選擇某個方案。

接下來介紹下如何做決策,在項目管理中有介紹“多標準決策分析”方法,這裏可以藉助此方法來幫助我們作出決策。

多標準決策分析:使用表格或其他方式,將重點關注的指標項定義好標準,以對衆需要決策內容進行評估和排序。

具體步驟:

  1. 根據目前迫切解決的問題拆解出衡量本次架構好壞的關鍵指標,爲每個關鍵指標制定出衡量標準;根據標準的相對重要性對標準進行加權;
  2. 根據衡量標準對所有備選方案評級或打分。
  3. 計算出各個備選方案的數學得分
  4. 然後根據得分對備選方案排序,然後根據排序後的方案列表確定最終備選方案。

在拆解衡量架構好壞指標時,需要遵循架構設計“合適原則”和“簡單原則”,指標能夠滿足一定時期內業務發展就可以了,避免貪大求全。

常見衡量架構方案的指標有:性能、可用性、硬件成本、項目投入、複雜度、安全性、可擴展性等

1.4 詳細方案設計

敲定整體方案後,接下來需要對整體方案進行細化,在本步驟中只需要將方案涉及的關鍵技術細節給確定下來。

何爲關鍵技術細節?以核心業務流程爲基準,將業務運作過程中涉及到技術,推演下如何支持業務運轉。例如目前用戶數量X億,在整體方案中敲定放使用MYSQL分庫分表存儲全量用戶數據,那在詳細方案中要完成時確定分庫分表的規則,如何解決分庫分表連表查詢等問題。

由於整體方案中涉及的技術架構師不一定全部精通,在此步驟中架構師需要對不熟悉的技術進行多次推演,確保該技術符合領域內的業務場景;除此之外,還需要深入瞭解下該技術出現的常見問題有哪些?如果出現該問題影響範圍是什麼?如何解決?是否可以規避這些問題?

二、架構設計流程實戰

當了解完架構設計的複雜性來源、架構設計的流程後接下來實戰一波,我們以京東商品詳情頁架構設計爲例。

在電商領域中,用戶從訪問首頁->搜索->商品詳情頁->支付->成單 是整個網站的交易關鍵路徑,網站的主要流量也集中在這幾個核心環節,商品詳情頁是從流量轉成實際交易的重要入口;聚合了商品、商品、評論、營銷活動、價格、廣告等衆多內容;同時爲了應對多變的商業環境,需要快速響應並支持各類需求,因此對該模塊的性能、穩定性、擴展性等都有很高的要求。

假設我們來設計商品詳情頁的架構,該如何設計呢?

2.1 識別複雜性

  • 高可用:依賴的其他服務的不可用都不應該直接影響詳情頁的展示;某個機器、某個機房、某個區域所有機房的不可用均不能影響整體的可用性。
  • 高性能:主流網站的詳情頁單接口響應時間一般在50ms左右,京東亦是如此;
  • 可擴展性:京東商城目前有通用版、全球購、閃購、易車、惠買車、服裝、拼購、今日抄底等許多套模板,個性化需求非常多,數據來源也是非常多的,如果一個需求對應一套模型,那麼開發成本太高了,如何開發一套擴展性強的支持多變的的、個性化需求較多的業務是不得不面的對架構問題;
  • 低成本:京東剛起步的時候,商品數量並不多,當入駐商家越來越多商品數量也達到了億級,此時就不得不考慮存儲的成本問題了。

2.2 整體方案

2.2.1 典型分佈式架構

  1. 性能:商品詳情頁具有讀多寫少特點,且短時間的緩存不一致也是可以接受的,對於不易變、有一定緩存不一致的數據進行緩存。
  2. 擴展性:
  • 簡單分層結構:服務層、網關層等採用分佈式架構,橫向擴展應對逐漸增長的用戶量;
  • 當頁面模板發生變化,只需要修改網關API,增加、減少服務層的依賴方,測試完可以很快上線。
  1. 可維護性:緩存時間不會很長,修改緩存結構時的臨時兼容代碼可以很快刪除。
  2. 可用性:採用分佈式集羣架構,當一臺服務器掛掉自動剔除故障節點。網關層提供統一的限流、降級等服務,當某個依賴服務完全不可用,修改開關剔除該服務的調用,避免影響整體服務的可用性。
  3. 低成本:服務是先去緩存查詢,當不存在時查詢數據放入緩存中;雖然是上億的商品,但實際訪問的不多,節省很多內存

缺點:

  1. 依賴服務的不穩定會直接影響詳情頁的可用性,雖然有降級等操作,但是從問題發生到發現的時間段還是挺長的。
  2. 依賴服務的性能會直接影響詳情頁的性能,即便使用異步、並行等,某個服務的響應時間過長也會影響整體響應速度。

2.2.2 平臺式架構

與典型分佈架構很像,差異點在與平臺式架構的網管層API只做聚合處理、降級、限流等通用功能,緩存、邏輯由各個服務層的團隊維護。

擴展性更強,每個團隊只維護自己的模塊即可,網關層API更簡單,不需要專門的人維護,更低的成本。

2.2.3 數據靜態化

拆分成多個子系統:統一模型數據生產系統,詳情服務系統,這裏簡單拆分兩個系統作爲示例說明。

運轉過程:將詳情頁依賴數據提前預加工到統一數據模型中,然後根據業務情況從統一數據模型中獲取數據再次加工成需要的聚合數據,提供給上游服務調用或詳情頁外其他業務方使用。

說明:

  1. 性能:提前預生成數據保存到高性能的KV存儲中,業務使用時無計算邏輯、整個調用棧深度較淺,性能很高。
  2. 擴展性:從各依賴方中獲取首次加工成統一數據模型,按照業務任意聚合、拆分,可以很容易支持業務需求。
  3. 可維護性:數據的生產、使用完全獨立分開,降低系統間的耦合。
  4. 可用性:數據生產、使用完全分開,依賴方的不可用不會影響到詳情頁。整體架構依然是分佈式集羣架構。

缺點:

  1. 當新增一個字段時,需要修改統一數據模型,修改的鏈路較長,需要重新刷所有存量數據;如果採用讀時修改會提高邏輯的複雜性,經過一兩年迭代大概率會新增字段很多字段,邏輯複雜性就會上一個臺階。
  2. 在本次架構中將網關層通過LUA腳本實現,團隊成員有一定的學習成本

2.3 評估和選擇方案

在本次案例中,按照識別的整體複雜性評估方案。

假設每個評分項是100分,接下來按照多個維度開始爲每個架構方案打分;其中性能、可用性優先級更好一些,因此權重更高一些,可在原基礎上增加20%,下文表格是未增加20%的數據;

性能評估:按照每天TP999來進行衡量,左開右閉,0-X1區間a分,X1-X2區間b分,X3-X4區間c分,大於X4d分。

可擴展性:按照新增同類需求開發時間、按照已有的業務發展預測幾個可能出現的業務,看下每種架構實現需要多少天,不同的時間天數設定不同分數。

可用性:假設某臺機器、某個機房、某個地域、某個依賴服務掛掉對業務的影響,可以以從故障發現到恢復的時間長短來衡量,左開右閉,0-X1秒內恢復a分,X1-X2區間b分,X3-X4區間c分,大於X4d分。

成本:每個方案需要使用多少臺數據庫、緩存、服務器等,每個規格數據庫、緩存、服務器單價是多少,數量*單價得出每個方案的成本。

對比項 典型分佈式 平臺式 數據靜態化
性能 X1 X2 X3
可擴展性 X1 X2 X3
可維護性 X1 X2 X3
可用性 X1 X2 X3
低成本 X1 X2 X3

綜合得出方案X性價比較高,選擇方案X爲最終的方案,下文假設使用數據靜態化爲最終方案。

2.4 詳細方案設計

在整體架構方案設計中保證了方案的可行性,接下來對具體實現的一些核心點進行細化。

細節點一:預生成的數據如何存儲?按照業務二次後的數據如何存儲?

答: 預生成的數據採用機械硬盤存儲即可,按照業務分類二次加工的數據採用與LevelDB類似的KV庫存儲,保證性能的同時降低整體成本。

細節點二:當某個依賴服務出現異常,統一數據模型數據沒有生成如何處理?某個依賴服務出現BUG,導致統一模型數據錯誤如何處理?

答: 統一數據模型提供多種刷新方式,當出現數據錯誤重新刷新即可。刷新方式有:全量數據刷新所有字段、按照條件刷新所有字段、全量數據刷新部分字段、按照條件刷新部分字段等多種刷新方式;刷新的時機有:定時刷新、異步消息通知刷新、手動部分刷新、實時刷新某個數據、延遲刷新某個數據等;當某個商品的數據沒有刷新到,可以採用延遲刷新或其他方式。

細節點三:團隊成員不熟悉LUA,如何應對?

答: lua屬於可選,當團隊成員對lua比較熟悉,那麼使用LUA替代網關層,好處是不需要一層轉發,降低整體成本。當團隊成員對LUA熟悉度不夠,編寫教程單獨爲成員進行培訓,並做實戰練習,當效果比較不錯就可以敲定了;如果實戰測試效果一般,則可以繼續使用原有的網關層。

細節點四:目前的都是可以緩存的,當出現不可緩存的該如何處理?例如頁面要展示每個SKU券後價,每個用戶的優惠券是不一樣的 答: 按照用戶做實時計算的邏輯應該與詳情頁分開,包含邏輯計算很容易成爲詳情頁的瓶頸,建議單獨設計,例如可以採用典型分佈式集羣架構。

細節點X:XXXX? 答: 就不一一列舉了。

三、商品詳情頁實戰

以下內容來自鏈接

3.1 1.0架構

IIS+C#+Sql Server,最原始的架構,直接調用商品庫獲取相應的數據,扛不住時加了一層memcached來緩存數據。這種方式經常受到依賴的服務不穩定而導致的性能抖動。

3.2 2.0架構

爲了解決線上服務不穩定的問題,在修改原架構採用頁面靜態化,由Java worker根據商品、商家等信息根據業務模板生成對應的HTML頁面,當有數據變更時,需要重新生成HTML;當用戶訪問商品詳情頁是,nginx直接訪問HTML頁面,不會有流量到後端服務器;

此架構的缺點就是當頁面有任何變更,都需要重新生成頁面;當一個通用的組件發生變化(例如導航欄發生變化),則需要重新生成全量商品詳情頁,當商品數量達到一定規模重新生成頁面就成了系統瓶頸。

3.3 2.X架構

爲了解決2.0中任一組件變化導致需要刷新整個商品詳情頁,將整個商品詳情頁按照模塊拆分,再通過Nginx SSI合併片段輸出完整商品詳情頁HTML。

似乎問題都解決了,然而我們卻忽略了頁面模板的變化,例如國際化頁面樣式需要調整,還是需要重刷所有商品頁面,還是無法從根本上解決問題。

3.4 3.0架構

對3.0架構的要求:

  1. 高擴展性:能迅速響應並支持需求;支持各種垂直化頁面改版
  2. 高性能:需要與頁面靜態化性能相差無幾
  3. 高可用:多機房多活、異地多活、水平擴容
  4. 低成本:在支持業務的同事儘量減少服務器的數量

此次架構核心思路是數據靜態化,前端只需開發好模板,後端直接返回預處理數據。

  1. 數據變更還是通過MQ通知
  2. 建立統一商品數據模型。對應圖中”數據異構“,將各方來源的數據更新到模型中,這樣就避免了依賴服務的不穩定導致商品詳情的不穩定;同時爲了提高穩定性,使用高性能、持久化、集羣架構KV技術存儲數據。
  3. 按照業務需求將商品詳情頁數據進行分類,從統一的數據模型按照分類進行聚合加工,結合nginx+lua這樣前端只需要調用一次接口就可以查詢到所有數據了。
  4. 拆分系統。將系統拆分爲數據異構系統、數據同步系統、各商品詳情數據分類系統等;雖然增加了複雜性,但是提高了整體的可用性。按照商品詳情數據分類的子系統如果業務有變更,只需修改這一個系統,擴展性也比較好;

在整個系統構建過程中大量使用異步,提供系統的併發能力,同時爲系統解耦。數據靜態成本相對於頁面靜態化成本要低很多,數據的存儲大小相對整個HTML要小的多。這樣就支持3.0架構的要求。

3.5 總結

在1.0架構中並沒有過多的設計,在當時已經有了”靜態化“架構,而沒有選擇該架構,正式因爲此架構剛好可以支持當時的公司規模;秉着簡單、合適原則選擇了1.0架構。

隨着業務規模的繼續發展,1.0架構已經無法支持,採用2.0架構來支持也符合當時業務場景;爲解決2.0架構中存在的一些問題最後迭代到3.0,整個架構的變遷符合演進原則。

從京東商品詳情頁架構設計也滿足了前面提到的三個基本原則:簡單、合適、演進;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章