分佈式系統架構

面試官們「愛不釋手」的分佈式系統架構到底是個什麼鬼?

轉載地址:http://www.imooc.com/article/288454

一、什麼是分佈式系統?

在談分佈式系統架構前,我們先來看看,什麼是分佈式系統?

假設原來我們有一個系統,代碼量30多萬行。現在拆分成20個小系統,每個小系統1萬多行代碼。

原本代碼之間都是直接基於Spring框架走JVM內存調用,現在拆開來,將20個小系統部署在不同的機器上,然後基於分佈式服務框架(比如dubbo)搞一個rpc調用,接口與接口之間通過網絡通信來進行請求和響應。

所以分佈式系統很重要的特點就是服務間要跨網絡進行調用,我們來看下面的圖:

https://img3.mukewang.com/5d121f610001ec3c04480271.jpg

此外,分佈式系統可以大概可以分成兩類。

1. 底層的分佈式系統。

比如hadoop hdfs(分佈式存儲系統)、spark(分佈式計算系統)、storm(分佈式流式計算系統)、elasticsearch(分佈式搜索系統)、kafka(分佈式發佈訂閱消息系統)等。

2. 分佈式業務系統

分佈式業務系統,把原來用java開發的一個大塊系統,給拆分成多個子系統,多個子系統之間互相調用,形成一個大系統的整體。

舉個例子,假設原來你做了一個OA系統,裏面包含了權限模塊、員工模塊、請假模塊、財務模塊,一個工程,裏面包含了一堆模塊,模塊與模塊之間會互相去調用,1臺機器部署。

現在如果你把他這個系統給拆開,權限系統,員工系統,請假系統,財務系統,4個系統,4個工程,分別在4臺機器上部署。

然後一個請求過來,完成這個請求,員工系統去調用權限系統,調用請假系統,調用財務系統,4個系統分別完成了一部分的事情。

最後4個系統都幹完了以後,才認爲是這個請求已經完成了。這就是所謂的分佈式業務系統。

同樣,我們來一張圖,感受一下上述過程:

https://img1.mukewang.com/5d121f7300019a8a06760490.jpg

 

二、爲什麼要走分佈式系統架構?

 

有的同學可能要問了,我一臺服務器跑的好好的,所有系統一個工程全部搞定,多好。爲啥一定要去搞什麼分佈式系統架構,互相調用還要走遠程,似乎還增加了不少工作量?

這裏我就以我曾經待過的一個公司的血淚經歷爲例,來聊聊這個問題。

很多年前,在沒有走分佈式架構的時候,我待的這家公司的各個業務線都是垂直的 「煙囪式」 項目。

隨着互聯網的快速發展,公司的業務也在不斷的發展,註冊用戶增加、網站應用的功能、規模不斷擴大,特別是移動互聯網的發展,APP、微信、自助終端機等訪問渠道的增加,各種新業務,新需求不斷涌入,系統遇到了各種各樣的問題。

首先是項目工程無節制的變得臃腫龐大,系統複雜度增加,大幾十萬行代碼,幾十個開發人員,service層,dao層代碼大量被copy使用,經常各種代碼合併衝突問題要處理,非常耗費時間。

經常是我改動了我的代碼,別人調用了我的接口,導致他的代碼也出現問題,需要重新測試,麻煩的要死。

然後每次發佈都是幾十萬行代碼的系統一起發佈,大家得一起提心吊膽準備上線,幾十萬行代碼的上線,每次上線都要做很多的檢查,很多異常問題的處理,每個人都高度緊張,被搞得幾乎崩潰。

而且如果我現在有個新業務,打算把相關依賴升級一下,比如升級到最新的spring版本,還不行,因爲這可能導致別人的代碼報錯,不敢隨意亂改技術。並且一個web工程每次啓動都需要好分鐘的時間,本地IDE裏面調試一次代碼都很痛苦。

其次,隨着用戶訪問流量的增加,系統負載壓力變大,變得不堪重負,通過增加實例數,增加硬件擴容能夠帶來的效果已微乎其微,故障頻發,效率低下。系統質量也越來越難以保證,測試周期也變得越來越長,無法滿足公司業務發展的需要。

以上就是以前待過的公司一些 「不堪回首」 的往事,總得來說,問題主要體現在以下幾個方面:

  1. 應用代碼耦合嚴重,功能擴展難

  2. 新需求開發交互週期長,測試工作量大

  3. 新加入的開發同事需要很長時間才能熟悉系統

  4. 升級維護也很困難(改動任何一點地方都要升級整個系統)

  5. 系統性能提升艱難,可用性低,不穩定。

好,既然我們已經深刻體會到了系統耦合的痛苦,那麼現在就來看看,系統拆分後帶來的好處:

首先,系統拆分了以後,會感覺整個世界都清爽了。

幾十萬行代碼的系統,假設拆分成20個服務,平均每個服務就1-3萬行代碼,每個服務部署到單獨的機器上。20個工程,就用20個git倉庫代碼,20個開發人員,每個人維護自己的那個服務就可以了。

  • 因爲是自己獨立的代碼,跟別人沒關係。再也沒有代碼衝突了,爽!

  • 每次就測試我自己的代碼就可以了,爽!

  • 每次就發佈我自己的一個小服務就可以了,爽!

  • 技術上想怎麼升級就怎麼升級,保持接口定義不變,輸入輸出內容不變就可以了,爽!

總結起來一句話,分佈式系統拆分之後,可以大幅度提升複雜系統大型團隊的開發效率。

 

三、系統如何進行拆分?

 

一般來說,將系統進行拆分,首先需要對系統整體比較熟悉。可以走多輪拆分的思路,第一次拆分就是將以前的各個大的模塊粗粒度的拆分開來。

比如一個電商系統可以拆分成訂單系統、商品系統、店鋪系統、會員系統、促銷系統、支付系統等等。

後面可能每個系統又變得越來越複雜了,比如說訂單系統又可以進一步拆分出來購物車系統,庫存系統,價格系統等。

總得來說就是基於領域驅動設計的思想以及實戰經驗總結,同時參考業界一些常規做法,大家討論着來進行拆分,逐步優化,多輪拆分,小步快跑,最終達到一個比較好的狀態。

 

四、分佈式之後帶來的技術挑戰?

 

首先就是分佈式服務框架的選用,目前國內來講主流的還是dubbo與spring cloud。

我們來思考一下,使用服務框架主要用來解決什麼問題呢?如果不用dubbo或者spring cloud是否可以做分佈式架構呢?

不用dubbo或者spring cloud等服務框架當然也是可以的,但是這就需要自己處理很多事情了。

比如,各個子系統走restful接口調用,那麼就是http調用,這時比如傳送過去一個對象,就要自己搞成一個json,然後一次調用失敗後重試怎麼做?

另外,一般來說都是集羣部署,目標系統有多個實例,那麼自己還要寫一個負載均衡算法,如何每次隨機從多個目標機器中挑選一個來調用?

還有,如果目標系統擴容新部署了一個實例,或者服務器故障下線了一個實例,如何動態讓調用方感知到呢? 諸如此類的很多問題,如果不用服務框架的話,自己這麼瞎搞,會遇到各種各樣的問題。

上述過程,用一張圖給大家呈現一下:

https://img3.mukewang.com/5d121f8e0001639706750281.jpg

如果選用了某一個分佈式服務框架,就需要深入的掌握這個框架的使用與底層原理,比如 dubbo 就需要搞明白以下的一些問題:

  1. dubbo的工作原理?

  2. dubbo支持的序列化協議?

  3. dubbo的負載均衡和高可用策略?動態代理策略?

  4. dubbo的SPI思想?

  5. 如何基於dubbo進行服務治理、服務降級、失敗重試以及超時重試?

  6. dubbo服務接口的冪等性如何設計(比如不能重複扣款,不能重複生成訂單,不能重複創建卡號)?

  7. dubbo服務接口請求的順序性如何保證?

  8. 如何自己設計一個類似dubbo的rpc框架?

使用spring cloud也是一樣,比如eureka的工作原理?feign聲明式調用的原理?等等各種底層原理要搞懂。

還有其它一些走分佈式架構後常見的要解決的技術問題:

  1. 分佈式會話

  2. 分佈式鎖

  3. 分佈式事務

  4. 分佈式搜索

  5. 分佈式緩存

  6. 分佈式消息隊列

  7. 統一配置中心

  8. 分佈式存儲,數據庫分庫分表

  9. 限流、熔斷、降級等。

以上這些問題,往深了說,每一個點都需要可能 N 篇文章來詳細闡述,這裏沒法逐一展開,後面我們會繼續通過一些文章,聊一聊這些分佈式架構下的各種技術問題。