點擊上方「JavaEdge」,關注公衆號
web
通常初創軟件,爲快速上線,幾乎不考慮分層。但隨業務愈加複雜,就會致使邏輯複雜、模塊相互依賴、代碼擴展性差等各類問題。數據庫
架構分層迫在眉睫。緩存
1 什麼是架構分層?安全
軟件工程中常見的設計方式,將總體系統拆分紅N個層次,每一個層次有獨立的職責,多個層次協同提供完整的功能。
微信
初學 JavaWeb 時通常要求設計成 MVC 架構。另一種常見的分層方式是將總體架構分爲網絡
表現層(Web)
展現數據結果和接受用戶指令的,是最靠近用戶的一層;架構邏輯層(Service)
複雜業務的具體實現;併發數據訪問層(Dao)
主要處理和存儲之間的交互。app
這就能夠隔離關注點,讓不一樣的層專一作不一樣的事情。其它分層案例,好比OSI網絡七層模型,TCP/IP協議網絡四層模型。運維
2 分層有什麼好處?
簡化設計
各司專職,而沒必要將本身活成全才。
高複用
好比在設計某系統時,發現某層具備通用性,就可把它抽取獨立出來,在設計其它系統時使用。
橫向擴展
可讓咱們更容易作橫向擴展。若是系統沒有分層,當流量增長時咱們須要針對總體系統來作擴展。可是,若是咱們按照上面提到的三層架構將系統分層後,就能夠針對具體的問題來作細緻的擴展。
好比業務邏輯裏面包含有比較複雜的計算,致使CPU成爲性能的瓶頸,那這樣就能夠把邏輯層單獨抽取出來獨立部署,而後只對邏輯層來作擴展,這相比於針對總體系統擴展所付出的代價就要小的多了。
架構分層究竟和高併發設計的關係是怎樣的?咱們知道橫向擴展是高併發設計思想之一,既然架構分層可方便橫向擴展, 那麼高併發系統必定是分層的。
3 如何架構分層?
關鍵在於理清層次邊界。
若按三層架構分層,邊界不就很容易界定嗎?
是的沒毛病,當業務邏輯簡單時,層次間邊界的確清晰,開發新功能時也知道把代碼往哪寫。但當業務邏輯愈來愈複雜,邊界也會變得模糊。
3.1 案例
任一系統都有用戶模塊,好比返回用戶信息的接口,它調用邏輯層的GetUser方法,GetUser方法又和User DB交互獲取數據,就像下圖左邊展現的樣子。
這時,產品提出一個需求,在APP中展現用戶信息的時候,若用戶不存在,那麼要自動給用戶建立一個用戶。同時,要作一個HTML5頁面保留以前的邏輯,即不須要建立用戶。這時邏輯層的邊界就變得不清晰,表現層也承擔了一部分的業務邏輯(將獲取用戶和建立用戶接口關聯)。
3.2 主流分層職責
MVC架構的簡單性讓太多的人以爲項目工程結構理所應當就是這樣的,而後呢,一大堆的業務邏輯就隨意的堆砌在了service中,對象啥的,只是單純的數據傳輸做用,出現了用面向對象的語言,寫面向過程的程序的廣泛現象。按照領域驅動設計的思路,最重要的還要有領域模型層。固然manage層這種方案也是一種思路,可是我以爲,這種方式,還不夠,必須有清晰的業務模型和合理的分層結構配合,才能更好的提現分層的做用。
終端顯示層
各端模板渲染並執行顯示的層。當前主要是 Velocity/framemaker渲染、js渲染、移動端展現等
開放接口層
將Service層方法封裝成開放接口,同時進行網關安全控制和流量控制等
Web層
主要是對訪問控制進行轉發,各種基本參數校驗,或者不復用的業務簡單處理等
Service層
業務邏輯層。調用manager層和dao層處理業務,即簡單的業務能夠不抽取manager,直接調用dao。
業務類的校驗放在service層,通常性的參數校驗能夠放在web層,這能夠通用化。
Manager 層(通用業務處理層)
DDD中也叫領域層。
能夠將原先Service層的一些通用能力下沉到這一層,好比與緩存和存儲交互策略,中間件的接入。業務邏輯放在manager,service來編排manager的原子服務。
也可在這一層封裝對第三方接口的調用,好比調用支付服務,調用審覈服務等
該分層架構相比MVC主要就是增長了Manager層,它與Service層的關係:Manager層提供原子的服務接口,Service層負責依據業務邏輯來編排原子接口。
業務邏輯就是你的產品邏輯,好比建立用戶要具體作什麼。
manager層的原子服務指的是實現單一功能的服務。
事務應該在service層
DAO層(數據持久層)
數據訪問層,與底層 MySQL、Oracle、HBase 等進行數據交互。緩存能夠放在存儲層。
外部接口或第三方平臺
包括其它部門 RPC 開放接口,基礎平臺,其它公司的 HTTP 接口
例如,Manager層提供建立用戶和獲取用戶信息的接口,Service層負責將這兩個接口組裝起來。這樣就把原先散佈在表現層的業務邏輯都統一至Service層,每層邊界就清晰了。
好比作一個接口,可將實現放在service層。以後公司內部調用邏輯可放在web層。而哪一天公司要開放這個接口,可直接新抽象一層(一個新的服務),即開放平臺層!這樣的好處是,能夠將本司使用和第三方使用作隔離。好比在提供服務時,爲了保證自家接口性能,對開放平臺層作限流處理。
傳統公司不少是分層部署的,好比保險和金融。service和dao部署在比較嚴密的網絡區域,controller層部署在一個較寬鬆的網絡區域,對外提供服務。等於在網絡上增長了一個緩衝區,來保證服務的安全;並且能夠經過單向網絡規範層級調用,controller能夠調用服務層,而服務層是不能調用web層的。
若是將數據訪問層單獨部署,好比拆分爲單獨的rpc服務,固然這樣拆分粒度比較細。controller就是對外的門面,調用單獨的服務層
能夠爲後期服務運維下降成本
能夠提升數據訪問層的複用度(數據訪問層對外提供API,其餘層的應用經過API方式與數據庫進行交互),三來能夠屏蔽各個數據庫實現的具體細節。
3.3 層間依賴
數據流轉只能在相鄰層間。以三層架構爲例,數據從表示層進入後必定要流轉到邏輯層,作業務邏輯處理,而後流轉到數據訪問層和DB交互。但若業務邏輯很簡單,能否從表示層直接到數據訪問層,甚至直接讀DB?
功能上是能夠的,但從長遠架構設計考慮,這會形成層級調用混亂,好比一旦DB地址變動,就需更改多層,這就失去了分層價值,且維護或重構都是災難。
4 架構分層的缺陷
4.1 增長代碼複雜度
本來可在接收請求後直接查詢DB得到結果,卻非要在中間多層設計,每層只簡單地作數據傳遞。
有時增長一個小需求,可能還需更改全部層的代碼,增長了開發成本,也增長了調試複雜度,增長了與其它模塊負責人的溝通成本。
4.2 性能損耗
若每層獨立部署,層間經過網絡交互,那多層架構勢必會在性能上有所損耗。
那是否還要選擇架構分層呢?確定的。
你要知道,任何的方案架構都是有優點有缺陷的,天地尚且不全況且咱們的架構呢?分層架構當然會增長系統複雜度,也可能會有性能的損耗,可是相比於它能帶給咱們的好處來講,這些都是能夠接受的,或者能夠經過其它的方案解決的。咱們在作決策的時候切不能夠偏概全,因噎廢食。
5 總結
分層架構是軟件設計思想的外在體現,是一種實現方式。一些軟件設計原則都在分層架構中有所體現。
比方單一職責原則規定每一個類只有單一的功能,在這裏可引伸爲每層擁有單一職責,且層與層之間邊界清晰;
迪米特法則原意是一個對象應當對其它對象儘量少的瞭解,在分層架構的體現是數據的交互不能跨層,只能在相鄰層之間進行;
開閉原則要求軟件對擴展開放,對修改關閉。它的含義其實就是將抽象層和實現層分離,抽象層是對實現層共有特徵的概括總結,不可修改,但具體實現可無限擴展,隨意替換。
參考
《阿里巴巴Java開發手冊》
往期推薦
目前交流羣已有 800+人,旨在促進技術交流,可關注公衆號添加筆者微信邀請進羣
喜歡文章,點個「在看、點贊、分享」素質三連支持一下~
本文分享自微信公衆號 - JavaEdge(Java-Edge)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。