前言
軟件剛出現(xiàn)的時候,還是大型計算機的年代,一個軟件系統(tǒng)一般都只會運行在一臺機器上。隨著軟硬件技術的革新,計算機體積和成本逐漸變小,此時工程師們發(fā)現(xiàn)一個軟件系統(tǒng)只運行在單臺機器上會存在各種瓶頸。如果將系統(tǒng)按照功能劃分成前端和后端,分別部署在兩臺服務器上,問題得到了緩解,于是便有了Client/Server架構的出現(xiàn)。
隨后,個人電腦的興起帶動了眾多富桌面應用(rich desktop application)的出現(xiàn),它們基于操作系統(tǒng)上的user interface開發(fā),數(shù)據(jù)則是存儲在單獨部署的database server上,通過標準的網絡協(xié)議進行數(shù)據(jù)通信。這種Desktop + Database Server的架構和C/S架構一樣,同屬 兩層架構 (two-tier architecture)。
隨著90年代互聯(lián)網的迅速崛起,Browser + Web Server + Database Server的組合也漸漸風靡。Browser為表現(xiàn)層,提供用戶交互界面;Web Server為業(yè)務層,處理具體的業(yè)務邏輯;Database Server為數(shù)據(jù)層,存儲系統(tǒng)數(shù)據(jù)。三個層次各司其職,這也是大家最熟悉的 三層架構 (three-tier architecture)。
上述的幾種架構模式都屬于 分層架構 (layered architecture)的范疇,分層架構并沒有限定一定得有多少個層次,層次的數(shù)量可以根據(jù)應用場景靈活控制,因此也被稱為 n-tier architecture 。它結構簡單,基于此架構進行系統(tǒng)開發(fā)成本也很低(很多公司在組織結構上劃分為前端工程師、后端工程師、DBA,根據(jù) 康威定律 ,這天然就具備了分層架構開發(fā)的良好條件),因此它在業(yè)界備受歡迎。 如果你的團隊還不確定選擇什么樣的架構,又或者為了踐行敏捷宣言中的“just starts coding“,那么分層架構會是一個不錯的選擇 。
架構視圖
在分層架構中,組件根據(jù)功能被劃分在不同的層次上,雖然層次的數(shù)量和類型并沒有被限制,但大多數(shù)的分層架構都由以下4層組成: 表現(xiàn)層 (presentation)、 業(yè)務層 (business)、 持久層 (persistence)和 數(shù)據(jù)層 (database),如下圖所示。在一些簡單的系統(tǒng)中,持久層的邏輯(如SQL)被嵌入到業(yè)務層中,形成了經典的三層架構;而在一些復雜的系統(tǒng)中,也會根據(jù)具體的業(yè)務劃分為五層甚至更多的層次。
分層架構的標準邏輯分層
前文所述的表現(xiàn)層等4個層次都是邏輯的劃分方法,在實際部署時,一般會有下圖所示的幾種部署形態(tài)。形態(tài)1中,表現(xiàn)層、業(yè)務層和持久層為一個部署單元,而數(shù)據(jù)層則單獨部署,具體表現(xiàn)為一個獨立部署的數(shù)據(jù)庫或文件系統(tǒng);形態(tài)2中,表現(xiàn)層被分離出單獨部署,業(yè)務層和持久層組成一個部署單元,數(shù)據(jù)層依舊是單獨部署的數(shù)據(jù)庫或文件系統(tǒng);形態(tài)3中,包括數(shù)據(jù)層在內的4層全都在同一個部署單元內,常見于業(yè)務簡單的系統(tǒng),它們往往使用的是嵌入式數(shù)據(jù)庫或內存數(shù)據(jù)庫。
分層架構的部署形態(tài)
分層架構中的每一層都扮演著各自的角色,比如表現(xiàn)層負責處理所有的用戶請求和瀏覽器交互,而業(yè)務層則負責執(zhí)行每次請求下的特定業(yè)務邏輯;表現(xiàn)層無需擔心從哪里獲取用戶數(shù)據(jù),它只需要將數(shù)據(jù)以特定的格式在瀏覽器上顯示即可。同樣地,業(yè)務層也無需關心用戶數(shù)據(jù)從何而來以及如何呈現(xiàn),它只需從持久層中取出數(shù)據(jù),執(zhí)行特定的業(yè)務邏輯(比如聚合數(shù)據(jù)),然后將結果返回給表現(xiàn)層。
每一層都是特定行為的抽象,這樣的職責劃分,使得組織能夠快速高效地創(chuàng)建出責任模型,圍繞各層打造開發(fā)團隊 。
層間隔離
分層架構中的每一層可以是封閉的或者開放的,封閉意味著當一個請求自頂向下在層間傳遞時,它不能跳過任意的一層。比如,當表現(xiàn)層接收到請求之后,它必須先后經過業(yè)務層和持久層才能到達數(shù)據(jù)層,如下圖所示。
封閉的分層架構
對于簡單的數(shù)據(jù)獲取類請求,如果讓表現(xiàn)層能夠直接訪問數(shù)據(jù)層獲取數(shù)據(jù),無疑是最簡單高效的。也即是讓業(yè)務層和持久層變成開放狀態(tài),允許請求在層間傳遞時跳過此層。那么, 究竟是封閉好,還是開放好呢 ?要解答這個問題,就要回到層間隔離的出發(fā)點上。
所謂的層間隔離,旨在降低一個層次上的變化對其他層次的組件的影響,簡單來說,就是每個層次對其他層次的功能知道的越少越好 。為了達到層間隔離的目的,就需要將每個層次置為封閉的狀態(tài)。假設表現(xiàn)層能夠直接訪問持久層,那么持久層的變化將會直接影響到業(yè)務層和表現(xiàn)層,這加劇了層間的耦合,導致系統(tǒng)變化的代價高昂。
層間隔離可以降低層次變化對系統(tǒng)的影響,凡事沒有絕對, 在某些的場景,將特定的層次置為開放的狀態(tài)也不失為一件好事 。考慮以下例子,業(yè)務層中存在著一些共享組件承載著業(yè)務層公共的功能(比如日志類、審計類、日期和字符串工具類等)?,F(xiàn)在有一項架構決策要求表現(xiàn)層不能直接訪問這些共享組件,但矛盾的是,原則上表現(xiàn)層是可以直接訪問業(yè)務層的,這種需要違反原則的決策將會很難落地。
業(yè)務層中的共享組件
一種解決方法是,新增一個服務層,該層包含了業(yè)務層的這些共享組件。因為業(yè)務層是關閉的狀態(tài),故表現(xiàn)層也就不能訪問到這些共享組件了。然而,新增的服務層必須置為開放狀態(tài),否則業(yè)務層將無法直接訪問持久層。新增一個服務層并置為開放狀態(tài),這樣既落地了架構決策,也不會影響到原有的功能,一舉兩得。
在分層架構中新增一個層次
一些注意事項
在使用分層架構時,需要注意以下兩點:
1、做好模塊的劃分
為分層架構做好模塊劃分主要是為后續(xù)的架構演進做好準備,比如在業(yè)務復雜到一定程度后演進為微服務架構時,各個模塊可以很自然地演進為微服務。為此,應該避免出現(xiàn)類的繼承層次過深的現(xiàn)象,這會導致代碼嚴重的耦合,不利于后續(xù)的架構演進。
2、避免掉進sinkhole反模式的陷阱
所謂sinkhole反模式指的是請求只是簡單地路過各個層次,并沒有做一些業(yè)務處理。
比如,表現(xiàn)層接收到一個獲取基本用戶數(shù)據(jù)(姓名、地址等)的請求后將它傳遞到業(yè)務層;然而,業(yè)務層并沒有做任何的業(yè)務處理,直接將請求傳遞到持久層;持久層也僅僅是構造了一個簡單的SQL語句,向數(shù)據(jù)層查詢用戶數(shù)據(jù);最后,數(shù)據(jù)按照原路返回到表現(xiàn)層,中途沒有經過任何的數(shù)據(jù)匯聚、轉換等操作。
sinkhole反模式會導致很多不必要的對象實例化開銷,從而增大了系統(tǒng)的內存消耗,并且影響了性能 。
然而,一個系統(tǒng)多多少少都會存在一些sinkhole反模式場景,要判斷一個系統(tǒng)是否已經徹底掉進sinkhole反模式的陷阱,主要還是看這類業(yè)務請求所占的百分比。根據(jù)20-80法則,當系統(tǒng)中有超過80%的業(yè)務請求是sinkhole類請求時,表示系統(tǒng)已經掉進sinkhole反模式的陷阱,這從側面也說明該系統(tǒng)已經不再適合分層架構,是時候考慮架構演進了。
綜合得分
分層架構的綜合得分
從綜合得分上看,分層架構的Overall cost和Simplicity得分很高,這很大程度上得益于分層架構本身是單體架構,少了很多分布式系統(tǒng)才有的復雜性。但這樣導致Deployability得分很低,因為3行代碼的改動就足以造成整個系統(tǒng)的重新部署。Testability得分不高也是這個原因,整系統(tǒng)的重新上線通常都需要將測試用例全部執(zhí)行一遍,多了不少額外的工作量。
Elasticity、Fault tolerance、Scalability這些都是單體架構天然的劣勢,自然地,分層架構在這些方面得分都很低。另外,sinkhole反模式的存在也拉低了分層架構在Performance上的得分。
總結
分層架構簡單而高效,業(yè)界已經有很多成熟的應用,對那些項目剛剛起步,架構師們還沒想好要采用哪種架構模式的系統(tǒng)而言,這是非常適合的。在實現(xiàn)分層架構時,我們需要合理地設置各個層次的封閉或開放狀態(tài),做好層間隔離,同時也要避免掉進sinkhole反模式陷阱。隨著業(yè)務的不斷擴張,分層架構在可維護性、可測試性、可擴展性等上的短板也會逐步被放大,此時就需要考慮往其他架構模式演進了。
每種架構模式都有其合適的應用場景,只有熟悉常用的幾種架構模式,才能設計出更好的軟件系統(tǒng)。下一篇文章,我們將繼續(xù)介紹 管道架構 。
-
服務器
+關注
關注
12文章
8958瀏覽量
85081 -
軟件
+關注
關注
69文章
4699瀏覽量
87087 -
機器
+關注
關注
0文章
777瀏覽量
40667 -
架構
+關注
關注
1文章
506瀏覽量
25430
發(fā)布評論請先 登錄
相關推薦
評論