|
1. 為什么分層?
計算機領域的體系結(jié)構(gòu)普遍采用了分層的方式。
從整體結(jié)構(gòu)來看:
從最底層的硬件往高層依次有:
操作系統(tǒng) -> 驅(qū)動程序 -> 運行庫 -> 系統(tǒng)程序 -> 應用程序等等。
從網(wǎng)絡分層模型OSI來講,由上至下為:
應用層 -> 表示層 -> 會話層 -> 傳輸層 -> 網(wǎng)絡層 -> 數(shù)據(jù)鏈路層 -> 物理層
當然實際應用的TCP/IP協(xié)議的分層就沒OSI標準這么復雜。
從C語言文件編寫到生成可執(zhí)行文件的過程來看:
預處理(展開后的C語言代碼) -> 編譯成匯編語言(特定CPU體系結(jié)構(gòu)的匯編語言源文件) -> 匯編器生成目標文件(CPU可執(zhí)行的二進制指令機器碼) -> 鏈接器連接目標文件生成可執(zhí)行文件(操作系統(tǒng)可以加載執(zhí)行的二進制文件)
這不算是軟件的分層結(jié)構(gòu),但是可以理解為一種通過分層來簡化復雜問題的思想。那么php語言可以認為是建立在C語言之上的層——其解釋器Zend引擎是用C語言實現(xiàn)。畢竟用php這樣的腳本語言編寫動態(tài)網(wǎng)頁要比用C語言方便得多。
當然還有我們最熟悉的MVC分層技術了,后面會做詳細介紹。
那么分層的好處想必大家都已經(jīng)比較熟悉,這是一種 “分而治之 大而化小” 的思想。說到分層就不得不提模塊了,其實分層和模塊是從兩種維度來進行“分而治之”的方式。模塊是從橫向維度來將一個整體分割成若干個獨立的部分,每個部分行使獨立自己的職責,當然它們之間也可能有依賴關系,這通過其對外提供的服務來實現(xiàn)。如果將整個系統(tǒng)比做中國版圖的話,那么模塊方式將中國分為省,自治區(qū)等。 分層則是從縱向緯度將一個整體從高至低劃分為若干個獨立的層,一個完整的服務由底層至上層,層層傳遞最終產(chǎn)出。分層和模塊可以同時運用,例如中國用模塊方式分為省之后,然后每個省的行政機構(gòu)利用分層方式來行使職責,從低到高有戶,村,鄉(xiāng),區(qū),市,省等等,每一層都向上一層匯報。 分層和模塊會提高系統(tǒng)復雜度并影響效率(戶不能直接向省匯報,而需要一級一級向上匯報),但是這樣有利系統(tǒng)的擴展和維護,每一層只需要關注自己提供的服務接口以及它下一層所提供的服務接口,試想一下如果省需要接受來自市,區(qū),鄉(xiāng),村等所有下級層的匯報,那些省干部會很頭疼的。
2. HTTP服務傳統(tǒng)的三層架構(gòu)MVC
HTTP服務中最經(jīng)典的分層架構(gòu)非MVC莫屬了, 幾乎任何一個php開發(fā)框架都是支持MVC分層模式,此模式歷史也比較悠久,是在上個世紀八十年代為編程語言Smalltalk設計的軟件模式,至今已經(jīng)被廣泛引用。
這里引用了百度百科中的圖片:
那么關于MVC的優(yōu)點我不做介紹,搜索引擎中能找到大量相關資料。
本文的標題是HTTP服務七層架構(gòu)技術探討,比MVC多出了四層,這樣復雜的分層是否有必要呢?
關于這個問題仁者見仁智者見智,本人認為MVC分層粒度不夠精細,當然你也可以繼續(xù)堅持傳統(tǒng)的三層,那么后文你也沒必要看下去了。
那么為什么MVC分層不夠精細呢,在我曾經(jīng)使用開源框架的MVC模式的經(jīng)驗中發(fā)現(xiàn),V和C層功能職責一般都很清晰穩(wěn)定,但是M層卻常常顯得臃腫笨拙。
C層主要是負責整體流程控制,一般規(guī)范的架構(gòu)中,流程都可以用一張或幾張流程圖畫出,那么表明流程一般都是固定的。
V層主要是負責頁面呈現(xiàn),可能使用smarty模板引擎,也可能是自帶的模板引擎,顯示的頁面可能是HTML,XML或則JSON,這些種類再多也都是可以度量的,所以M層也可以說是固定的。
而M層卻關系到系統(tǒng)的業(yè)務邏輯,隨著系統(tǒng)不斷迭代更新,M層中的內(nèi)容也會不斷演變,而這一層中也有很多復雜的處理,如文件讀取,數(shù)據(jù)庫查詢,緩存策略,邏輯運算,數(shù)據(jù)加工,數(shù)據(jù)打包等等。
所以MVC三層模型中,M層是還能再做細分的,當M層有一個更精細合理的分層方式之后,我們的業(yè)務邏輯演變過程會更加的得心應手。
3. 七層架構(gòu)
由上面的介紹,那么我們對MVC中的M層再進行分層規(guī)劃,我這里給出的是一種對M層分五層的方式,讀者如果覺得五層太多或則太少那么可以參考這個再進行規(guī)劃。
原來的M層被分為:
A層:Application 應用層
B層:Business 業(yè)務層
C層:Component 組件層
D層:Datadriver 數(shù)據(jù)驅(qū)動層
S層:Systemdriver 系統(tǒng)驅(qū)動層
那么整個七層架構(gòu)則為:
1. Controller
2. View
3. Application
4. Business
5. Component
6. Datadriver
7. Systemdriver
結(jié)構(gòu)圖還是參考經(jīng)典MVC,將其中M層換成新的五層即可。
現(xiàn)在依次介紹這幾個新的層:
1. Application
應用層在最上面,其針對實際中的單個頁面或則單個接口。Controller通過HTTP請求地址中的參數(shù)找到對應的Application,然后執(zhí)行中指定的公共方法,比如main(),然后應用就開始啟動。應用層的職責包括接受HTTP參數(shù)(一般是間接接受,比如從request對象中獲取),調(diào)用Business層的特定業(yè)務,保存業(yè)務執(zhí)行結(jié)果,這些結(jié)果最終會由View顯示出來,當然是通過Controller協(xié)調(diào)。應用層是M層分解成五層之后最高的層,Controller會與此層直接通信。
2. Business
業(yè)務層在應用層之下,通常一個應用實例對應一個業(yè)務實例,而一個業(yè)務有可能為多個應用服務,業(yè)務是一個執(zhí)行流,它通過執(zhí)行一系列的操作來完成應用的需求。這些操作來自下層的組件層Component,可能一個業(yè)務需要一個或則多個組件來完成一個完整的需求。因為一個業(yè)務實例通常只對應一個功能,所以只有一個固定的方法會被上層的應用調(diào)用,比如flow()。業(yè)務層的職責是幫應用層執(zhí)行業(yè)務流并且有必要的時候返回數(shù)據(jù)給應用層,它會調(diào)用下層Component的方法。
3. Component
從組件層開始和上面兩層有一個本質(zhì)的區(qū)別,組件層開始有了類庫的概念。 前面兩層的實例通常只暴露一個特殊約定的公共的方法讓上層調(diào)用,從這一層開始一個實例會提供多個方法給上層。組件層通常和系統(tǒng)中一個角色對應,例如在博客系統(tǒng)中,博文是一個角色,用戶是一個角色,那么就會有博文組件BlogComponent,用戶組件UserComponent,每個角色都有對應的操作,例如博文和用戶都可以添加刪除修改。
需要注意組件層中不應該有任何數(shù)據(jù)讀取的操作,數(shù)據(jù)讀取是下層數(shù)據(jù)驅(qū)動層來做的。如果組件層從下層獲取了數(shù)據(jù),那么它的一個職責就是對數(shù)據(jù)進行加工。例如BlogComponent有一個方法是獲取一個博文getBlog($id),那么getBlog()方法中,從數(shù)據(jù)驅(qū)動層中取得了對應id的博文數(shù)據(jù)之后,需要對博文數(shù)據(jù)進行一定的處理,比如將博文中的HTML特殊標簽過濾等等。組件層不關心數(shù)據(jù)的讀取方式,但是會關心數(shù)據(jù)的結(jié)果,比如數(shù)據(jù)不存在或則數(shù)據(jù)已經(jīng)過期。
4. Datadriver
數(shù)據(jù)驅(qū)動層的職責是為組件層提供源數(shù)據(jù),此層關心數(shù)據(jù)的存取介質(zhì),存取方式等等。數(shù)據(jù)可能被存儲在DB,MC,F(xiàn)ilesystem或則遠程的HTTP服務器上。數(shù)據(jù)驅(qū)動層不關心數(shù)據(jù)的內(nèi)容,只關心數(shù)據(jù)讀取的操作結(jié)果,例如假設數(shù)據(jù)存在DB中,但是數(shù)據(jù)驅(qū)動層在執(zhí)行數(shù)據(jù)庫查詢的時候出錯了,那么需要在此層處理。 假設數(shù)據(jù)存儲在遠程的HTTP服務器上,那么數(shù)據(jù)驅(qū)動層需要關心HTTP返回碼是否為正確的200系列或則錯誤的400,500系列,哪怕HTTP請求返回了錯誤的數(shù)據(jù)實體,但是返回碼為200,那么數(shù)據(jù)驅(qū)動層也不關心,這種情況需要上層組件層來處理。
5. Systemdriver
系統(tǒng)驅(qū)動層是系統(tǒng)環(huán)境提供的數(shù)據(jù)訪問實例,例如數(shù)據(jù)庫服務的Systemdriver可能是一個db handler,HTTP服務的Systemdriver可能是一個http handler,文件存儲系統(tǒng)驅(qū)動層可能是一個file handler, 系統(tǒng)驅(qū)動層相對簡單,這層可以和數(shù)據(jù)驅(qū)動層進行合并,其職責也較少。僅僅只是執(zhí)行數(shù)據(jù)驅(qū)動層的數(shù)據(jù)訪問指令。
通常情況下這五個層中,上層的實例數(shù)量比下層的實例數(shù)量要多, 整體類似一個倒置的梯形:
在上圖中一共有6個Application,5個Business,4個Component,3個Datadriver,2個Systemdriver。
每個Application都由一個Business為其服務。
每個Business都服務一個或則多個Application(B5同時服務A5 A6),都有一個或則多個CompoNET為其服務。
每個Component為一個或則多個Business服務,都有一個或則多個Datadriver為其服務。
每個Datadriver為一個或則多個Component服務,都有一個或則多個Systemdriver為其服務。
每個Systemdriver為一個或則多個Datadriver服務。
4. 七層架構(gòu)運用
現(xiàn)在運用這樣的架構(gòu)來設計一個簡單的博客系統(tǒng),服務端用php語言實現(xiàn)。當然,架構(gòu)是思想,不區(qū)分語言。
整個系統(tǒng)包含以下功能
1. 發(fā)布博文 2.修改博文 3.刪除博文 4.評論博文 5.修改用戶信息
要求每個功能都記錄操作日志。
設計的數(shù)據(jù)存儲包括
1. 博文數(shù)據(jù)表 2.用戶數(shù)據(jù)表 3.評論數(shù)據(jù)表 4. 日志(存文件系統(tǒng))
在表結(jié)構(gòu)設計的時候我們加入了一些冗余字段信息,例如在博文表中有評論數(shù)量字段comment_nums, 博文每被評論一次其值加1,每刪除一個評論其值減1
用戶數(shù)據(jù)表中我們添加了用戶發(fā)布的博文數(shù)量字段blog_nums,用戶每發(fā)布一篇博文其值加1,每刪除一篇博文其值減1
下面設計分層:
1. PostBlogApplication 發(fā)布博文
2. UpdateBlogApplication 修改博文
3. DeleteBlogApplication 刪除博文
4. CommentBlogApplication 評論博文
5. UpdateUserApplication 修改用戶信息
業(yè)務層:這5個應用分別有5個業(yè)務對其服務
1. PostBlogBusiness 博文發(fā)布業(yè)務
2. UpdateBlogBusiness 博文修改業(yè)務
3. DeleteBlogBusiness 博文刪除業(yè)務
4. CommentBlogBusiness 博文評論業(yè)務
5. UpdateUserBusiness 用戶修改業(yè)務
組件層:系統(tǒng)一共有4個角色對應4個組件
1. BlogComponent 博文組件
提供方法包括
1> postBlog() 發(fā)布博文
2> deleteBlog()刪除博文
3> updateBlog()修改博文
4>getBlog()獲取博文內(nèi)容
2. CommentComponent 評論組件
提供方法包括
1>postComment() 發(fā)布評論
2> deleteComment() 刪除評論
3. UserComponent 用戶組件
提供方法包括
1> updateUser() 修改用戶信息
4. LogComponent 日志組件
提供方法包括
1>logMsg() 記錄日志信息
數(shù)據(jù)驅(qū)動層:和4個組件對應
1. BlogDatadriver DB類型 提供blog的select insert delete update
2. CommentDatadriver DB類型 提供comment的select insert delete update
3. UserDatadriver DB類型 提供user的select insert delete update
4. LogDatadriver FS類型 提供file的read write
系統(tǒng)驅(qū)動層: DB類型和FS類型
1. MySqlSystemdriver DB的handler
2. FileSystemdriver FS的handler
現(xiàn)在以發(fā)布博文操作來介紹流程。假設接口地址為: http://www.xxxxx.com/postBlog:
1. Controller通過重寫規(guī)則發(fā)現(xiàn)其對應的Application為PostBlogApplication,于是PostBlogApplication被實例化,并且其中的特殊方法main()會被自動調(diào)用。
2. postBlogApplication需要PostBlogBusiness業(yè)務來完成博文發(fā)布操作,PostBlogBusiness被實例化,并且其中的特殊方法flow()會被調(diào)用。
3. 根據(jù)需求,發(fā)布博文的時候需要在博文表中插入一條博文,然后修改用戶信息中的博文數(shù)量字段。那么postBlogBusiness業(yè)務流就包括兩個操作,這兩個操作分別由BlogComponent中的postBlog()方法和UserComponent 中的updateUser()方法來實現(xiàn),其中前者往博文表中插入博文信息,后者將用戶信息中的博文數(shù)量字段加1。由于系統(tǒng)要求任何操作都需要記錄日志,因此還有第三個操作就是記錄日志,通過BlogComponent的logMsg()方法實現(xiàn)。那么PostBlogBusiness業(yè)務流一共包括了三個操作,分別由三個組件來完成。
4. 下面就需要分別考慮上面三個組件的下層調(diào)用了
其中BlogCompoNET的postBlog()調(diào)用BlogDatadriver的insert相關方法來插入博文數(shù)據(jù),BlogDatadriver是DB類型,因此通過MySqlSystemdriver 來實現(xiàn)。
UserComponent的updateUser()調(diào)用UserDatadriver的update相關方法來實現(xiàn)博文數(shù)量更新,UserDatadriver也是DB類型,因此也通過MySqlSystemdriver 來實現(xiàn)。
LogComponent的logMsg()調(diào)用LogDatadriver的write相關方法,LogDatadriver是FS類型,因此通過FileSystemdriver 來實現(xiàn)。
5. 三個組件的操作都執(zhí)行成功后,PostBlogBusiness告訴postBlogApplication博文發(fā)布成功,然后postBlogApplication通過Controller來調(diào)用View相關的方法顯示執(zhí)行結(jié)果。
其他幾個操作流程讀者可以舉一反三,這里不再多介紹了。
那么現(xiàn)在我們通過幾個系統(tǒng)功能的演變用例來看看這個分層帶來的益處。
用例1:為了方便對日志的管理,現(xiàn)在希望能夠?qū)⑷罩?a href=/pingce/cunchu/ target=_blank class=infotextkey>存儲在DB中而不是FS中。
解決方法:這是對數(shù)據(jù)存儲的改造,我們知道應該從數(shù)據(jù)驅(qū)動層入手。日志功能是由日志組件LogComponent實現(xiàn)的, 其中LogCompoNET的了logMsg()方法調(diào)用LogDatadriver 來存日志。我們將LogDatadriver由FS類型改造成DB類型,接口方法保持不變,這樣很快就完成了改造。
用例2:新增需求-用戶A可以將一篇博文轉(zhuǎn)移給另外一個用戶B。
解決方法:
步驟1. 首先這個新需求對應了一個新的應用,于是我們新增了一個SendBlogApplication。
步驟2. 需要有一個業(yè)務完成操作,新增業(yè)務為SendBlogBusiness。
步驟3. 考慮轉(zhuǎn)移一篇博文涉及到的操作 1.將博文表中對應的用戶ID字段由A的ID切換到B的ID;2.A用戶的博文數(shù)量減1;3.B用戶的博文數(shù)量加1。
這三個操作需要兩個組件來完成,這兩個組件我們系統(tǒng)中已經(jīng)有了,BlogComponent的updateBlog ()完成操作1,UserComponent的updateUser()完成操作2,3。
從用例2可以看出,當新增了這么一個需求的時候,我們在應用層和業(yè)務層添加了實例,組件層以下都不變,這是因為現(xiàn)在的組件層已經(jīng)能夠滿足新的業(yè)務的需求,當我們現(xiàn)有組件無法滿足新的一業(yè)務需求的時候,我們則需要對組件層做修改。
通過這兩個簡單的用例我們發(fā)現(xiàn)我們對系統(tǒng)的修改要么可以很明確的確定在哪些層,要么就是從上層組件往下層進行,操作起來很方便。
5. 小結(jié)
這種縱向的分層和橫向的模塊結(jié)合起來,能讓整個系統(tǒng)的結(jié)構(gòu)清晰流暢,在本人設計的一款框架里面,原生的支持這樣的分層架構(gòu)和模塊,使用者只需要按照同一個模式簡單的操作,層之間的接口和協(xié)議已經(jīng)由框架本身約定好,框架還不夠完善,自己內(nèi)部用用可以,暫時不發(fā)布了。
it知識庫:HTTP服務七層架構(gòu)技術探討,轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。