分層單體架構風格是分層思想在單體架構中的應用,其關注于技術視角的職責分層。
同時,基于不同層變化速率的不同,在一定程度上控制變化在系統內的傳播,有助于提升系統的穩定性。
但這種技術視角而非業務視角的關注點隔離,導致了問題域與工程實現之間的Gap,這種割裂會導致系統認知復雜度的提升。
1 經典單體分層架構
1.1 四層單體架構風格
經典的四層單體分層架構如下圖所示,應用在邏輯上劃分為展現層、業務層、持久層及數據存儲層,每層的職責如下:
展現層:負責給最終用戶展現信息,并接受用戶的輸入觸發系統的業務邏輯。用戶可以是使用系統的人,也可以是其他軟件系統。
業務層:關注系統業務邏輯的實現
持久層:負責數據的存取
數據存儲層:底層的數據存儲設施
這種分層單體架構可能是大多數開發人員最早接觸、最為熟悉的應用架構風格,其特點是:
層間的依賴關系由上到下逐層向下直接依賴,每層都是關閉狀態,請求的數據流向從上到下,必須嚴格通過每個分層進行流轉,而不能進行穿透調用。
關注點隔離:通過分層將系統的關注點進行垂直分配,每層只關注自身層邊界內的職責,層間職責相互獨立不存在交叉。比如業務層負責處理系統的核心業務邏輯,而持久層則關注于對數據的存取。
除了關注點隔離這一維度,分層也在 “變化” 的維度進行隔離。每層的變化速率不同,由下級上逐層增加,展現層的變化速率最快,數據存儲層變化速率最低。
通過嚴格層依賴關系約束,盡量降低低層變化對上層的影響。這個特點的上下文是分層之間依賴于抽象,而非依賴于具體。
當實現發生變化而接口契約不變時,變更范圍框定在當前層。但,如果是接口契約的變更,則可能會直接影響到上游的依賴層。
這種分層架構風格具有明顯的優勢:
分層模型比較簡單,理解和實現成本低
開放人員接受度和熟悉程度高,認知和學習成本低
1.2 五層單體架構風格
四層架構面臨的問題是:
層間數據效率問題: 由于層間調用關系的依賴約束,層間的數據流轉需要付出額外成本
業務層服務能力的復用性:業務層中處于對等地位的組件或模塊之間存在共享服務的訴求
從復用性的角度考慮,如下所示的五層架構中,通過引入中間層解決復用問題。將共享服務從業務層沉淀到通用服務層,以提高復用性。其特點是:
引入通用服務層提供通用服務,提高復用性
通用服務層是開放層,允許調用鏈路穿透,業務層可以按需直接訪問更下層的持久層
相比于四層架構,五層分層架構的主要優勢是:通過中間層的引入一定程度解決系統的復用性問題。但從反向角度看,正是由于中間層的引入導致了如下問題:
引入中間層降低了數據傳輸效率,提高了開發實現成本
有造成系統混亂度提升的風險:由于通用服務層的開放性導致業務層可以穿透調用。
但這種是否需要進行穿透的場景無法形成統一的判定原則,往往依賴于實現人員的個人經驗進行權衡,同一個業務場景由不同的開發人員實現可能會有不同的判定結果(在四層架構中如果放開層間調用約束也會存在該問題)。隨著業務需求迭代,系統的依賴關系一定會日趨增加,最終形成復雜的調用關系,也導致系統復雜性上升,增加團隊成員的認知成本。
2 單體分層架構的共性問題探討
當然,正是由于其極高的接受度,也造成了大家對分層的認知誤區,認為分層是必然的“默認選項” ,從而忽略了分層的本質。分層到底是為了解決什么問題?
分層本質上是處理復雜性的一種方式:將復雜性在不同級別進行抽象,通過分層進行職責隔離,以此降低認知成本。同時,通過分層形成的“屏障”,控制變化在系統間的傳播,提升系統穩定性。
不論是四層架構還是五層架構都是分層思想在單體應用架構風格下的實踐,這種分層模式存在的固有問題主要體現在以下幾個方面:
分層對系統復雜度和效率的影響
變化真的能完全隔離嗎?
問題域與解決方案的隔離
2.1 分層對系統復雜度和效率的影響
如上文所述,分層架構中各層的變化速度不同。越往上變化越快,穩定性越低,越往下變化越慢,穩定性越高。比如,展現層的用戶展示邏輯可能頻繁變化,對應于不同的場景訴求展示數據及形式都可能不同。
如果劃分層次越多,層間依賴關系越嚴格,則系統的調用鏈路和依賴關系會更加清晰。但,請求及響應的鏈路越長,層間數據轉換有額外成本。即使引入各種數據轉換工具,比如MapStruct,實現起來依然會感覺非常繁瑣和重復。
如果劃分層次越多,層間依賴關系寬松,允許跨層調用(如下所示的從展現層調用持久層只是一個示意),則能在一定程度降低數據頻繁轉換的成本。但:
其一:如何判定是否要跨層調用很難形成統一的嚴格判定標準,只能進行粗粒度劃分。因此,在實現過程中會有不同的判定結果,系統的調用關系會隨著代碼規模增長而日趨復雜。當然,團隊可以加強代碼評審的粒度,每次評審基于是否穿透調用進行討論、判斷并達成一致。但實際經驗是,由于人為因素,靠嚴格的代碼評審并不能保證決策的一致性。
其二:如果允許跨層調用,則意味著 “模型” 的穿透,低層的模型會直接暴露在更上層,這與我們追求的組件內聚性和模型的封裝性存在沖突
注:層間的依賴約束是一種架構決策,可以考慮通過自動化單元測試機制進行保證
2.2 變化的隔離
我們對分層有一個普遍的、“先入為主” 的認知,分層能夠隔離變化。首先會想到的例子,比如,如果底層的數據庫發生了變更,又或者ORM框架發生了變更,那么,我們只需要修改DAO層的實現,而不需要更改上層的業務層代碼。
你真的會替換數據庫嗎?你真的會替換ORM框架嗎?有可能,但概率非常低,大部分系統并不會發生這種場景。
發生替換就真的能隔離嗎?如果你的層間不是依賴于抽象,而是依賴于具體,那么隔離也無從談起。
即使層間依賴于抽象,變化就真的隔離了嗎?實現發生變化的直接結果就是依賴方需要引用新的實現,這種變化也同樣會影響到上層。只不過是基于現在的普遍技術棧,這種變化交由IOC容器了
但,這個變化隔離的全部嗎?
如果是展現層需要增加一個新的字段,而當前數據庫模型中沒有?
如果是數據庫中需要增加一個新的字段,而展現層和業務邏輯層不關心?
如果是......
所以,引起系統變化的原因很多,場景各異,業務訴求亦不相同,分層對變化隔離程度也不相同:
分層可以控制變化在系統內的傳播,由于變化場景的多樣化,分層不能完全的隔離變化。
2.3 問題域與解決方案的割裂
重新思考下上文提到的分層單體架構的特點之一:關注點隔離,展現層、業務層、數據訪問層、存儲層等各層聚焦于自身的職責。這種關注點的本質是什么?
技術視角的隔離!!!
每層都是從技術視角將技術關注點進行隔離,而非業務領域視角。技術視角是研發友好的,作為開發人員,天然的可以理解和接受這種技術維度的統一語言:DAO層只負責處理數據相關邏輯,Controller層之服務處理Restful API相關,RPC層只處理與外部系統的跨進程調用等等。
而對于非常核心的業務概念,比如以訂單為例,在單體分層架構下需要回答這樣一個問題:“訂單組件” 在哪里?
在經典的分層單體架構風格中,典型的實現如下圖所示:
OrderConroller:Spring技術棧下的系統訪問的Rest接口
OrderService/OrderServiceImpl:訂單的核心業務邏輯實現服務,實現諸如下單、取消訂單等邏輯
OrderDAO/OrdeDAOImpl:訂單數據的存取
訂單組件并不是以一個單一的、內聚的事物存在,其組成元素OrderService以及其依賴的OrderDAO分散于不同的層,因此,這種模式下訂單組件只是邏輯性、概念性的存在。作為業務域的核心抽象,訂單組件沒有真實的、直觀的、內聚的反映在代碼實現中。我們在工程代碼庫中尋找“訂單組件”:
首先,在工程頂層最先看到的是技術視角的Module(Maven Module):web、service 、dao
然后,需要在各層導航才能一窺其全貌
在IDE的支持下,這種導航并不會很復雜。但問題的根本在于:認知成本的增加。
我們去了解系統,天然的是從業務域而非技術域出發,單體分層恰恰是從技術域而非業務域出發,這種不同導致業務域與實現間的割裂,增加了對系統的認知成本。
實現要反應抽象,組件化思維本質上一種模塊化思維,通過內聚性和封裝性,將問題空間進行拆分成子空間,分而治之。對外通過接口提供組件能力,屏蔽內部的復雜性。接口契約的大小粒度需要權衡,粒度越小,能力提供越約聚焦,理解和接入成本越低,但通用性越差。接口契約粒度越大,則通用性越強,但理解和接入復雜性越高。
將組件化思維應用于單體分層架構,引申出模塊化單體架構風格。應用架構按照問題域進行模塊化組織,而非基于技術關注點進行拆分。組件內部遵循內聚性原則,其內包含了實現組件能力所需要的各個元素及交互關系。組件之間通過統一的、合適粒度的接口契約進行交互,不直接依賴于組件的內部能力或模型。
同時,組織良好的模塊化單體應用架構也是進行微服務拆分的重要保證。如果你無法在單體架構中進行優雅的模塊化組織,又何談合理的微服務拆分呢?
3 結語
單體分層架構風格是分層思想在單體架構中的應用,其關注于技術視角的職責分層。同時,基于不同層變化速率的不同,在一定程度上控制變化在系統內的傳播,有助于提升系統的穩定性。但這種技術視角而非業務視角的關注點隔離,導致了問題域與工程實現之間的Gap,這種割裂會導致系統認知復雜度的提升。
將組件化思維應用于單體分層架構,模塊化單體技術視角的分層拉回至業務域視角的模塊化,一定程度上降低了業務于工程實現間的隔離。良好的模塊化是單體走向微服務的重要基石,如果模塊化設計較差的系統,不僅會增加微服務拆分的成本,更為重要的是,會增加拆分后形成分布式單體的概率和風險。
審核編輯:劉清
-
數據存儲
+關注
關注
5文章
970瀏覽量
50894 -
RPC
+關注
關注
0文章
111瀏覽量
11529 -
IOC
+關注
關注
0文章
28瀏覽量
10099
原文標題:分層單體應用架構的本質
文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論