目錄:
一、什么是分布式系統?
二、為什么要走分布式系統架構?
三、系統如何進行拆分?
四、分布式之后帶來的技術挑戰?
一、什么是分布式系統?
在談分布式系統架構前,我們先來看看,什么是分布式系統?
假設原來我們有一個系統,代碼量30多萬行。現在拆分成20個小系統,每個小系統1萬多行代碼。
原本代碼之間都是直接基於Spring框架走JVM內存調用,現在拆開來,將20個小系統部署在不同的機器上,然后基於分布式服務框架(比如dubbo)搞一個rpc調用,接口與接口之間通過網絡通信來進行請求和響應。
所以分布式系統很重要的特點就是服務間要跨網絡進行調用,我們來看下面的圖:

此外,分布式系統可以大概可以分成兩類。
1. 底層的分布式系統。
比如hadoop hdfs(分布式存儲系統)、spark(分布式計算系統)、storm(分布式流式計算系統)、elasticsearch(分布式搜索系統)、kafka(分布式發布訂閱消息系統)等。
2. 分布式業務系統
分布式業務系統,把原來用java開發的一個大塊系統,給拆分成多個子系統,多個子系統之間互相調用,形成一個大系統的整體。
舉個例子,假設原來你做了一個OA系統,里面包含了權限模塊、員工模塊、請假模塊、財務模塊,一個工程,里面包含了一堆模塊,模塊與模塊之間會互相去調用,1台機器部署。
現在如果你把他這個系統給拆開,權限系統,員工系統,請假系統,財務系統,4個系統,4個工程,分別在4台機器上部署。
然后一個請求過來,完成這個請求,員工系統去調用權限系統,調用請假系統,調用財務系統,4個系統分別完成了一部分的事情。
最后4個系統都干完了以后,才認為是這個請求已經完成了。這就是所謂的分布式業務系統。
同樣,我們來一張圖,感受一下上述過程:

二、為什么要走分布式系統架構?
有的同學可能要問了,我一台服務器跑的好好的,所有系統一個工程全部搞定,多好。為啥一定要去搞什么分布式系統架構,互相調用還要走遠程,似乎還增加了不少工作量?
這里我就以我曾經待過的一個公司的血淚經歷為例,來聊聊這個問題。
很多年前,在沒有走分布式架構的時候,我待的這家公司的各個業務線都是垂直的 “煙囪式” 項目。
隨着互聯網的快速發展,公司的業務也在不斷的發展,注冊用戶增加、網站應用的功能、規模不斷擴大,特別是移動互聯網的發展,APP、微信、自助終端機等訪問渠道的增加,各種新業務,新需求不斷涌入,系統遇到了各種各樣的問題。
首先是項目工程無節制的變得臃腫龐大,系統復雜度增加,大幾十萬行代碼,幾十個開發人員,service層,dao層代碼大量被copy使用,經常各種代碼合並沖突問題要處理,非常耗費時間。
經常是我改動了我的代碼,別人調用了我的接口,導致他的代碼也出現問題,需要重新測試,麻煩的要死。
然后每次發布都是幾十萬行代碼的系統一起發布,大家得一起提心吊膽准備上線,幾十萬行代碼的上線,每次上線都要做很多的檢查,很多異常問題的處理,每個人都高度緊張,被搞得幾乎崩潰。
而且如果我現在有個新業務,打算把相關依賴升級一下,比如升級到最新的spring版本,還不行,因為這可能導致別人的代碼報錯,不敢隨意亂改技術。並且一個web工程每次啟動都需要好分鍾的時間,本地IDE里面調試一次代碼都很痛苦。
其次,隨着用戶訪問流量的增加,系統負載壓力變大,變得不堪重負,通過增加實例數,增加硬件擴容能夠帶來的效果已微乎其微,故障頻發,效率低下。系統質量也越來越難以保證,測試周期也變得越來越長,無法滿足公司業務發展的需要。
以上就是以前待過的公司一些 “不堪回首” 的往事,總得來說,問題主要體現在以下幾個方面:
- 應用代碼耦合嚴重,功能擴展難
- 新需求開發交互周期長,測試工作量大
- 新加入的開發同事需要很長時間才能熟悉系統
- 升級維護也很困難(改動任何一點地方都要升級整個系統)
- 系統性能提升艱難,可用性低,不穩定。
好,既然我們已經深刻體會到了系統耦合的痛苦,那么現在就來看看,系統拆分后帶來的好處:
首先,系統拆分了以后,會感覺整個世界都清爽了。
幾十萬行代碼的系統,假設拆分成20個服務,平均每個服務就1-3萬行代碼,每個服務部署到單獨的機器上。20個工程,就用20個git倉庫代碼,20個開發人員,每個人維護自己的那個服務就可以了。
- 因為是自己獨立的代碼,跟別人沒關系。再也沒有代碼沖突了,爽!
- 每次就測試我自己的代碼就可以了,爽!
- 每次就發布我自己的一個小服務就可以了,爽!
- 技術上想怎么升級就怎么升級,保持接口定義不變,輸入輸出內容不變就可以了,爽!
總結起來一句話,分布式系統拆分之后,可以大幅度提升復雜系統大型團隊的開發效率。
三、系統如何進行拆分?
一般來說,將系統進行拆分,首先需要對系統整體比較熟悉。可以走多輪拆分的思路,第一次拆分就是將以前的各個大的模塊粗粒度的拆分開來。
比如一個電商系統可以拆分成訂單系統、商品系統、店鋪系統、會員系統、促銷系統、支付系統等等。
后面可能每個系統又變得越來越復雜了,比如說訂單系統又可以進一步拆分出來購物車系統,庫存系統,價格系統等。
總得來說就是基於領域驅動設計的思想以及實戰經驗總結,同時參考業界一些常規做法,大家討論着來進行拆分,逐步優化,多輪拆分,小步快跑,最終達到一個比較好的狀態。
四、分布式之后帶來的技術挑戰?
首先就是分布式服務框架的選用,目前國內來講主流的還是dubbo與spring cloud。
我們來思考一下,使用服務框架主要用來解決什么問題呢?如果不用dubbo或者spring cloud是否可以做分布式架構呢?
不用dubbo或者spring cloud等服務框架當然也是可以的,但是這就需要自己處理很多事情了。
比如,各個子系統走restful接口調用,那么就是http調用,這時比如傳送過去一個對象,就要自己搞成一個json,然后一次調用失敗后重試怎么做?
另外,一般來說都是集群部署,目標系統有多個實例,那么自己還要寫一個負載均衡算法,如何每次隨機從多個目標機器中挑選一個來調用?
還有,如果目標系統擴容新部署了一個實例,或者服務器故障下線了一個實例,如何動態讓調用方感知到呢? 諸如此類的很多問題,如果不用服務框架的話,自己這么瞎搞,會遇到各種各樣的問題。
上述過程,用一張圖給大家呈現一下:

如果選用了某一個分布式服務框架,就需要深入的掌握這個框架的使用與底層原理,比如 dubbo 就需要搞明白以下的一些問題:
- dubbo的工作原理?
- dubbo支持的序列化協議?
- dubbo的負載均衡和高可用策略?動態代理策略?
- dubbo的SPI思想?
- 如何基於dubbo進行服務治理、服務降級、失敗重試以及超時重試?
- dubbo服務接口的冪等性如何設計(比如不能重復扣款,不能重復生成訂單,不能重復創建卡號)?
- dubbo服務接口請求的順序性如何保證?
- 如何自己設計一個類似dubbo的rpc框架?
使用spring cloud也是一樣,比如eureka的工作原理?feign聲明式調用的原理?等等各種底層原理要搞懂。
還有其它一些走分布式架構后常見的要解決的技術問題:
- 分布式會話
- 分布式鎖
- 分布式事務
- 分布式搜索
- 分布式緩存
- 分布式消息隊列
- 統一配置中心
- 分布式存儲,數據庫分庫分表
- 限流、熔斷、降級等。
以上這些問題,往深了說,每一個點都需要可能 N 篇文章來詳細闡述,這里沒法逐一展開,后面我們會繼續通過一些文章,聊一聊這些分布式架構下的各種技術問題。