業務拆分的思考
從最初的單體應用,即將進行業務拆分,分而治之,雖心不免有些激動,但是很快就陷入深思。
因為我不得不考慮如何拆分比較好及其現在要不要拆分的問題。
目前我們開發的是一個多租戶系統應用,考慮到公共通用功能,例如使用者功能、組織功能、選單功能、模組功能、系統監控、審批功能、許可權管理等,我們將其作為公共模組,而像共享方面的系統或者是智慧門鎖方面的系統,我們決定將其抽象另外的模組,當特定的使用者需要該功能時,只需與我方溝通簽訂對應的合作協議,我方後臺超級管理員只需配置下相應的許可權即可。
一、先談談是否要拆分的問題
孫子曰:“不盡知用兵之害者,則不能盡知用兵之利“。
還是回到之前的那個問題,業務是否真正需要拆分呢?這裡要結合具體的業務需求。
比如,目前我對這個多租戶系統有這麼樣一個想法,如果要拆分,按照上述的原則公共模組進行抽取,抽取為一個後臺web應用。
而像共享方面(例如共享汽車等)和智慧門鎖可單獨作為另外的一個應用。之所以這麼做的原因在於處於如下考慮:
(1)解耦性和可維護性
如果所有的系統都要放入一個龐大的war下,那麼程式碼耦合度可能會比較高,而且不易維護,就好比git分支開發,之所以強調每個人在自己的分支下開發對應的功能模組,是因為避免全部都在主分支開發時,導致出現的程式碼混亂和衝突問題。另外還有一個考慮是,通常主分支,也就是master分支,一般情況下,主分支的程式碼是不存在問題的,或者問題非常小,但是由於都在主分支上進行開發,導致有的時候,因為沒有嚴格的程式碼稽核機制,導致有些開發人員,比如曾經的我,僅僅只是為了完成任務而開發,寫程式時,很少思考不考慮到是否會不會影響到其他同事的程式碼,最後的結果是,陷入的一個死迴圈,改bug,改bug....
之所以強調可維護性,是因為,對於這個多租戶而言,後臺模組單獨作為一個應用,由部分人負責,而像智慧門鎖或者是共享汽車等應用是另外一個模組,也由專門的開發人員負責,這樣一來,你打你的我打我的,總的原則,堅持一個,“高內聚,低耦合,程式碼可讀性良好,可擴充套件性良好”。
當然了,實際情況也不能你打你的,我打我的,各自為戰,該及時溝通還是得及時溝通,對於專案組長而言就需要時刻了解自己的組員工作進度及其程式碼方面的情況,因為這樣一來當專案經理問起時,也不必膽戰心驚。
作為專案經理,處於整個專案的領路人,專案的成敗,很大程度不僅僅是由底層的開發人員所決定,還有就是專案經理的決策和管理。
(2)穩定性
有這麼一句話,“雞蛋不能同時放在一個籠子下”。
後臺應用,一般情況下僅僅只是管理人員使用,或者是管理員通過許可權分配指定某一些人使用。這樣一來,基本上,不用考慮高併發。
而像智慧門鎖這樣的,不得不考慮高併發和效能方面的問題,如果全部將其放在一個war下,一個出問題,全部出問題,將會導致宕機,影響專案的正常服務,容錯性差。
這樣看來,業務拆分,也是為了提高穩定性。
二、談談業務拆分的思路
(1)梳理所有的業務功能環節
主要以粗分為主,例如智慧門鎖系統的智慧門鎖、智慧閘道器等等這樣的。
(2)業務功能細分
例如智慧門鎖系統中的智慧門鎖,它不僅包含門鎖列表展示、安裝門鎖、門鎖詳情資訊、門鎖授權人、一次性密碼和系統密碼等,還包括如何開鎖等等。
(3)梳理業務主體,進行分門別類劃分
這裡主要強調的是將業務分類,類似開發中的緊急並非常重要、緊急但不重要這樣的開發優先順序。
(4)將金字塔結構圖結合業務泳道圖通過關鍵指標來識別關鍵業務功能
也許這句話不是特別好理解,比較官方,不過當我說完後,你一定會非常明白。
其實整個專案就是一個金字塔結構
從頂層到下層,自頂向下,如圖(畫的有點醜,大家湊合著看吧)
根據這幅圖可歸納為如下四點:
a. 將所有的通過用業務邏輯組成公共服務,比如配置服務,排程服務,快取服務等;
b.如果有一個業務主體,得到了各方面的關注,那麼就把這個業務首先拆分出來獨立成一個模組;
c.長流程業務就符合業務主體特殊一條標準,可以提取為一個獨立的服務;
d. 分渠道,比如將介面呼叫的邏輯和介面方式的邏輯解耦成兩個服務,比如後臺和介面,使得兩個變成獨立的管道互不影響;
(6)重構
拆分的過程也意味著對程式碼進行重構。
a.首先拆除所有的公共服務(校驗服務,規則服務,開通服務,歸檔服務),然後再拆分特殊業務主體服務(重點業務,長流程業務),最後拆不同驅動實現方式(介面服務和介面服務);
b.因為業務量特別大,系統採用訊息佇列的方式進行處理,通過接骨法接觸程式碼之間的耦合,並提供對外服務的介面;
c. 比如建立訂單的環節,設計所有的業務主體,影響大,所以這個服務不能一下子全拆出來,要通過修路法,先建設一個訂單服務和原來的系統並行使用,同時分流出幾個試點業務到訂單服務。當上下游呼叫沒有問題,可以正常建立訂單後,再通過分批逃跑法,逐步地將其他業務的處理遷移到這個微服務上面,最終當所有的業務都遷移成功之後,原來的系統的訂單處理邏輯就廢棄了;
d.業務的拆分過程中,資料庫拆分的工作也同時進行(主從和讀寫分離);
三、分散式拆分
提到分散式,普及下什麼是分散式系統,這裡我引用圖片:
引用百度百科:
分散式系統(distributed system)是建立在網路之上的 ofollow,noindex">軟體 系統。正是因為 軟體 的特性,所以分散式系統具有高度的 內聚性 和透明性。因此,網路和分散式系統之間的區別更多的在於高層 軟體 (特別是 作業系統 ),而不是硬體。 內聚性 是指每一個 資料庫 分佈節點 高度自治 ,有本地的 資料庫管理系統 。透明性是指每一個 資料庫 分佈節點對使用者的應用來說都是透明的,看不出是本地還是遠端。在 分散式資料庫系統 中,使用者感覺不到資料是分佈的,即使用者不須知道關係是否分割、有無 副本 、資料存於哪個站點以及 事務 在哪個站點上執行等。
關於分散式拆分,我主要圍繞三個方面講,需求,原則,方法等三個方面。
(1)需求
a.組織結構變化
從最初的一個團隊逐漸成長並拆分為幾個團隊,團隊按照業務線不同進行劃分,為了減少各個業務系統和程式碼間的關聯和耦合,幾個團隊不再可能共同向一個程式碼庫中提交程式碼,必須對原有系統進行拆分,以減少團隊間的干擾。
b.安全
這裡所指的安全不是系統級別的安全,而是指程式碼或成果的安全,尤其是對於很多具有核心演算法的系統,為了程式碼不被洩露,需要對相關係統進行模組化拆分,隔離核心功能,保護智慧財產權。
c.替換性
有些產品為了提供差異化的服務,需要產品具有可定製功能,根據使用者的選擇自由組合為一個完整的系統,比如一些模組,免費使用者使用的功能與收費使用者使用的功能肯定是不一樣的,這就需要這些模組具有替換性,判斷是免費使用者還是收費使用者使用不同的模組組裝,這也需要對系統進行模組化拆分。
d.互動速度
單體程式最大的問題在於系統錯綜複雜,牽一髮而動全身,也許一個小的改動就造成很多功能沒辦法正常工作,極大的降低了軟體的交付速度,因為每次改動都需要大量的迴歸測試確保每個模組都能正確工作,因為我們不清楚改動會影響到什麼,所以需要做大量重複工作,增加了測試成本。這時候就需要對系統進行拆分,理清各個功能間的關係並解耦。
e.技術需求
單體程式由於技術棧固定,尤其的是比較龐大的系統,不能很方便的進行技術升級,或者說對引入新技術或框架等處於封閉狀態;每種語言都有自己的特點,單體程式沒有辦法享受到其它語言帶來的便利;對應到團隊中,團隊技術相對比較單一。
相比於基於業務的垂直拆分,基於技術的橫向拆分也很重要,使用資料訪問層可以很好的隱藏對資料庫的直接訪問、減少資料庫連線數、增加資料使用效率等;橫向拆分可以極大的提高各個層級模組的重用性。
f.業務需求
由於業務上的某些特殊要求,比如對某個功能或模組的高可用性、高效能、可伸縮性等的要求,雖然也可以將單體整體部署到分散式環境中實現高可用、高效能等,但是從系統維護的角度來考慮,每次改動都要重新部署所有節點,顯然會增加很多潛在的風險和不確定定性因素,所以有時候不得不選擇將那些有特殊要求的功能從系統中抽取出來,獨立部署和擴充套件。
(2)原則
a.業務優先
每個系統天然都會按業務功能分成多個模組,每個模組又包含許多業務相關的功能,在系統拆分時,我們就可以優先考慮按照業務邊界進行切割,切割完成後再針對每個模組進行拆解,循序漸進,逐漸迭代深入,最終完成系統的拆解。這個過程類似庖丁解牛,要找到關節之處下刀,方能事半功倍。
b.迴圈漸進
系統拆分過程中包含兩個非常重要的工作:拆分和測試。二者缺一不可,並且二者是並行進行的,一定要邊拆分邊測試。每一步拆分完成都要保證系統功能是完整的,保證系統的測試是完整的。拆分要小步前進,如此以來可以減少累計錯誤的發生。這一點在《重構》這本書中也講到了。
c.兼顧技術
系統不能為了分散式而分散式,系統拆分的代價相當昂貴;當然如果有拆分的需要,我們也不能白白浪費這麼好的學習機會:
可靠測試:“重構之前,首先檢查自己是否有一套可靠的測試機制”,這是MartinFowler在《重構》這本書中說到的,它同樣對系統拆分有效。拆分是在對系統進行大手術,每一次的改動都要保證系統保持原來的行為不變。測試使得我有足夠的信心進行下一步的拆分或重構,不至於在錯誤的道路上越走越遠,以至於錯誤累積。測試與拆分如影隨形,每一步都要有足夠的測試。沒有測試的拆分和重構我真的不敢想象結果會是什麼樣子。
關於測試的重要性可以參考我的這篇文章:論單元測試之重要性
之前我強調過,測試由底層的單元到高層的UI,其中單元是最有利於發現問題解決問題的。
(3)方法
a.公共模組複用;
b.增加代理,解耦;
小結:
本文主要講三個大方面,第一個是業務拆分是否有必要拆分;第二個是業務拆分的思路;最後一個是分散式業務拆分。
本文的重點在於第一個和第二個,因為這兩個我深有體會,試驗過,應用過。至於分散式的話,此次主要普及下相關的知識和給有這方面需求的人啟發。
本文主要參考如下兩篇文章:
業務系統拆分的基本思路:https://blog.csdn.net/u011402896/article/details/80506394
分散式拆分:https://blog.csdn.net/zzz34k/article/details/52576731
當然了,也加上了我自己的理解和想法。
希望能給廣大的IT友友們帶來有益的收穫。