為什麼需要應用拆分
我以淘寶技術架構演進為例,淘寶從一個大系統工程向分佈式架構演變過程,你就能很清楚的知道為什麼要需要進行應用拆分。
1 人員的角度。
維護一個代名工程Denali的百萬級代碼怪獸(雖然物理部署是分離的),從發佈到上線,從人員的角度,百號人同時在一個工程上開發,一旦線上出問題,所有代碼都需要回滾,從人員的角度,也基本忍受到了極致。
2 業務的角度
淘寶包含太多業務:用戶、商品、交易、支付…等等,所有的代碼早期都在denali一個工程裡,代碼已經嚴重影響到業務的效率,每個業務有各自的需求,需要給自己應用部署,各自開發需求。
3 從架構的角度
從數據庫端oracle數據庫集中式架構的瓶頸問題,連接池數量限制(oracle數據庫大約提供5000個連接),數據庫的CPU已經到達了極限90%。數據庫端也需要考慮垂直拆分了。
4.急需走向一個大型的分佈式時代,率先需要應用拆分。
1 )首先工程代碼垂直拆分
把整個工程代碼按照業務為單元進行垂直拆分。
淘寶按照業務為單位拆分成了類似這樣的系統:UM(UserManger)、SM(ShopManager)..等等幾十個工程代碼。
2 )應用服務拆分
按照業務為單位,把所有調用相關的接口以業務為單元進行拆分。
比如,一個店鋪系統,需要訪問一個用戶的頭像的接口,用戶頭像的接口是獨立部署在用戶中心(UIC)這邊的集群服務器上的。隨著拆分的進行,淘寶的業務接口中心就變成了:UIC(用戶中心服務)、SIC(店鋪中心服務)等等以業務為單元部署的集群。
最終就演變成下圖,按照業務為單位拆分和部署服務,用戶中心、商品中心等:
總之,系統拆分是單體程序向分佈式系統演變的關鍵一步,也是很重要的一步,拆分的好壞直接關係到未來系統的擴展性、可維護性和可伸縮性等,拆分工作不難理解,但是如何正確拆分、有什麼樣的方法和原則能幫助我們拆分得到一個我們理想中的系統:高可用、可擴展、可維護、可伸縮的分佈式系統。
以下主要再從拆分需求、拆分原則和拆分步驟談起:
拆分需求
1、組織結構變化:從最初的一個團隊逐漸成長並拆分為幾個團隊,團隊按照業務線不同進行劃分,為了減少各個業務系統和代碼間的關聯和耦合,幾個團隊不再可能共同向一個代碼庫中提交代碼,必須對原有系統進行拆分,以減少團隊間的干擾。
2、安全:這裡所指的安全不是系統級別的安全,而是指代碼或成果的安全,尤其是對於很多具有核心算法的系統,為了代碼不被洩露,需要對相關係統進行模塊化拆分,隔離核心功能,保護知識產權。
3、替換性:有些產品為了提供差異化的服務,需要產品具有可定製功能,根據用戶的選擇自由組合為一個完整的系統,比如一些模塊,免費用戶使用的功能與收費用戶使用的功能肯定是不一樣的,這就需要這些模塊具有替換性,判斷是免費用戶還是收費用戶使用不同的模塊組裝,這也需要對系統進行模塊化拆分。
4、交付速度:單體程序最大的問題在於系統錯綜複雜,牽一髮而動全身,也許一個小的改動就造成很多功能沒辦法正常工作,極大的降低了軟件的交付速度,因為每次改動都需要大量的迴歸測試確保每個模塊都能正確工作,因為我們不清楚改動會影響到什麼,所以需要做大量重複工作,增加了測試成本。這時候就需要對系統進行拆分,理清各個功能間的關係並解耦。
5、技術需求:
1)單體程序由於技術棧固定,尤其的是比較龐大的系統,不能很方便的進行技術升級,或者說對引入新技術或框架等處於封閉狀態;每種語言都有自己的特點,單體程序沒有辦法享受到其它語言帶來的便利;對應到團隊中,團隊技術相對比較單一。
2)相比於基於業務的垂直拆分,基於技術的橫向拆分也很重要,使用數據訪問層可以很好的隱藏對數據庫的直接訪問、減少數據庫連接數、增加數據使用效率等;橫向拆分可以極大的提高各個層級模塊的重用性。
6、業務需求:由於業務上的某些特殊要求,比如對某個功能或模塊的高可用性、高性能、可伸縮性等的要求,雖然也可以將單體整體部署到分佈式環境中實現高可用、高性能等,但是從系統維護的角度來考慮,每次改動都要重新部署所有節點,顯然會增加很多潛在的風險和不確定定性因素,所以有時候不得不選擇將那些有特殊要求的功能從系統中抽取出來,獨立部署和擴展。
如何拆分
1.拆分原則
- 單一職責
- 服務粒度適中
- 考慮團隊結構
- 以業務模型切入
- 演進式拆分
- 避免環形依賴和雙向依賴
2.分佈式應用拆分實戰
下面是拆分代碼過程實踐經驗:
1). 設計module骨架
module骨架的設計是基礎,影響最終拆分結果,拆分成功的嚮導。按照技術,業務,部署打包,測試這幾個維度來規劃設計,下面是一個參考。
最終骨架模型層級:
root web app
webapp //war module,打包為單體war,整體部署
micro-services //微服務pom module
user-service
customer-service
order-service
other-service
api-gateway
biz //業務相關的module
entitys //所有實體類
biz-base //一些無法拆分的代碼上有依賴的服務
biz-user //用戶業務
biz-customer //客戶業務
biz-order //訂單業務
...
commons
async-framework //一部框架
utils //工具類
2). 拆分技術commons
作為第一步,先對整個工程按業務和功能進行了maven多module的拆分。
首先是分離出技術上的commons,感覺這應該是最好拆分的了,把相關的類重構到一個包裡,在分離出一個module即可。
3). 拆分entity
很多在業務代碼上都會共享entity類,通常沒法也沒法把entity類分門別類,最簡單就是把所有的entity類放到一個module,誰需要誰依賴的原則。entity類也沒有太多jar依賴和業務依賴,也不會形成汙染源。
4)公共業務
同commons和entity方法,不在複述,也被各個業務依賴,這種業務大部分是過渡性的,在未來迭代演進時可以通過其他方式抽象集成。
5)拆分業務代碼
拆分業務是最痛苦的事情了,這個要看原來的代碼整潔度和互相依賴程度,一般採取2中方法:
- 新建業務module,加入基礎module的pom依賴,再從源module複製和該業務module相關的代碼(包括單元測試代碼)過來,解決編譯錯誤和單元測試錯誤,完成本業務拆分。
- 從源module複製一個新業務module,保持代碼一致,先刪除和本義務無關的代碼(包括單元測試代碼),再刪除無關的pom依賴,解決編譯錯誤和單元測試錯誤,完成本業務拆分。
選擇哪種方法,可以根據代碼整潔度和互相依賴程度,如果代碼很整潔且相互依賴較弱,可以採取前者,否則就採取後者。
6)拆分微服務
有了以上的拆分基礎,可以在合適的業務迭代將各個微服務module遷移到不同的代碼倉庫,完成進一步隔離管理。
微服務架構框架
業界開源微服務架構框架提供了微服務的關鍵思路,例如 Dubbo 和 Spring Cloud(請關注後續文章,我會詳解區別和優劣勢)
Dubbo是Alibaba開源的分佈式服務框架,它最大的特點是按照分層的方式來架構,使用這種方式可以使各個層之間解耦合(或者最大限度地松耦合)。
Spring Cloud是一個微服務框架,相比Dubbo等RPC框架, Spring Cloud提供的全套的分佈式系統解決方案。
微服務架構是互聯網技術發展的必然結果,它提倡將單一應用程序劃分成一組小的服務,服務之間互相協調、互相配合,為用戶提供最終價值。
分佈式架構之應用拆分總結:
1.明確拆分原則和拆分需求。
2.梳理出業務模塊和之間的依賴關聯關係。
3.按照業務為單位,拆分實體、以及應用工程單獨部署。
4.按照業務為單位拆分應用服務,避免環形依賴和雙向依賴。
5.抽離出公用的接口、實體,以及服務單獨部署為公用服務。
閱讀更多 優知學院 的文章