[转]实用体系结构:逻辑分层
原文鏈接http://msdn.microsoft.com/zh-cn/library/aa905336.aspx
發布日期 : 2006-11-29 | 更新日期 : 2006-11-29
Ted Neward
適用于:
.NET Framework
摘要:為什么我們就要使用 n(物理)層體系結構來構建系統?這是一篇基礎性的文章,介紹了人們對于軟件的一種理念,即當我們面對新項目時往往將系統明確地分為三個物理層次:表現層、業務邏輯層和數據訪問或資源層。然而,對于循規蹈矩的做事方式應當重新審視。
有些事物是如此堅定地挺進了我們的通俗文化之中,以至于不發生災難性的事故就無法將其擯棄,即使它們早已不能適應我們的生活。這樣的例子在法律界比比皆是,在當今時代或其他時代美國的市、州甚至聯邦政府針對無意義的書籍都有相關的法律(據說,在亞利桑那州的某個小鎮上,在公路中間倒車是違法的)。這不禁使人聯想到一個老笑話:
一個剛結婚的男人看到妻子正在準備晚餐要吃的烤肉。他吃驚地發現,妻子在將肉放到烤盤中前,分別在兩端切掉了大約兩英寸的肉,然后扔掉。而當男人對妻子的這一行為表示驚訝時,妻子回答道“這會使肉的味道更好。而且,我的媽媽也總是這樣做”。他好奇地給岳母打了電話,問她是否也切掉烤肉的兩端,以及這樣做的原因。“因為這會使肉的味道更好。而且,我的媽媽也總是這樣做”。男人決心找出這個習慣的源頭,于是又給妻子的外婆打了電話,當外婆回答她在準備烤肉的時候也要切掉肉的兩端時,男人又接著問為什么。外婆立刻回答說“因為我的盤子太小了,裝不下整塊肉”。
毫無疑問,對于這種明顯的循規蹈矩的做事方式應當重新審視。但遺憾的是,其他情況并不都如此顯而易見。
例如,為什么我們就要使用 n(物理)層體系結構來構建系統?這是一篇基礎性的文章,介紹了人們對于軟件的一種理念,即當我們面對新項目時往往將系統明確地分為三個物理層次:表現層,用以處理所有用戶輸入和數據顯示問題;業務邏輯層,存放所有“業務邏輯”(本身是一個完全無定性的名詞,可準確表示說話者希望其表達的意思);數據訪問或資源層,存放用于檢索、修改或存儲數據的所有代碼。當被問道為什么要這樣做時,許多人只能說出最普通的答案,“因為我的老師(或前任主管或剛讀過的一本書)總是這種做”。與普通的進程內調用相比,跨物理層通信會帶來高達三到六個數量級的巨大性能成本,兩者的差距就相當于一個是到樓下雜貨店而另一個是到冥王星。(請參閱《Effective Enterprise Java》(有效的企業 Java)第 17 條)。僅僅因為媽媽總是這樣做,我們就要丟掉好肉… 嗯 CPU 周期嗎?
歸根結底,請記住以物理分層的方式構建應用程序并不是開發人員的唯一選擇。舉個例子,想想 UNIX 開發人員早已熟知而 .NET 開發人員隨著 Microsoft Windows PowerShell 的即將推出才開始領悟到的一個真諦:將小部件分割成可以互饋的片段可以創建出一些功能極強的合成工具,避免了用來維護復雜應用程序所需的相應復雜性。例如,對一般的 C# 或 Visual Basic 語言開發人員而言,創建一個能夠在文本文件中搜索并替換某個字符串序列的工具可能是件容易的工作,而這對于掌握 PowerShell 的人則更加顯得微不足道,因為它只需串聯幾個“cmdlets”:其中一個用于遍歷文件,另一個用于搜索文件內容并用新文本替換所搜索的文本,第三個用于將新內容寫入磁盤。這是一個非常好的模型。具體而言,由于每個組件都能夠專注于特定的任務(遍歷、搜索、寫入),從而簡化了它們的維護和設計工作。
在匆忙地對 n(物理)層模型做出審判之前,它應該得到一次救贖的機會。對于初學者,我們可以對過于通用的“n 層”一詞的使用稍加重新界定,并指出“物理層”和“邏輯層”的重要區別。(請參閱 Martin Fowler 的《Patterns of Enterprise Application Architecture》(企業應用體系結構的模式),閱讀關于這一主題的完整論述。)
“邏輯層”是對軟件的邏輯分割,是在開發人員級對各關注點的基礎分割,這樣我們可以更加容易地劃分系統的職責。這在 [POSA1] 中有進一步的論述。在這本書中談及邏輯層模式時講到,使用邏輯層“有助于構筑可以分解為子任務組(每組子任務處于某個抽象級別)的應用程序”。換句話說,它是對各關注點的典型分割方式:將企業系統中所涉及的各種任務(包括檢索數據、存儲數據、針對數據執行業務規則、顯示數據、搜集輸入值等等)分割為組件或子節,以便我們能夠更加輕松地跟蹤在何時何處發生了什么。當然,最為常見的方式是將任務分為“表現”、“邏輯”和“數據訪問”(邏輯)層。但請注意,我們并沒有立即假定每個邏輯層將在“哪里”運行,目前還沒有。
而另一方面,“物理層”是硬件(通常是某種形式的計算機)的物理分層,我們系統的一部分或全部可以運行于其上。傳統的客戶機/服務器計算(即寫入可以針對運行于單獨服務器上的數據庫執行 SQL 語句的程序)是一個由兩個物理層構成的系統。我們每天都享用的萬維網也是在兩(物理)層方法的基礎上構建的,其中一個物理層(即客戶機)位于某人的家中或辦公室內并遠程訪問位于某處服務器機房中的另一個物理層。這樣的例子數不勝數。
這似乎有些文不切題。歸根結底,表現層不總是在客戶計算機上嗎?數據訪問層不總是在數據庫服務器上嗎?而業務邏輯層不總是在前兩者之間某處的計算機上嗎?我們來進一步研究一下基于 Web 的典型三(物理)層應用程序模型:
-
基于 Web 的應用程序中的“表現”邏輯層是 Web 瀏覽器,因此不在我們的掌控之中。瀏覽器將要顯示的 HTML 通常必須從服務器內所運行的某種形式(ASP 或 ASP.NET)的代碼組件中生成并被發送給瀏覽器。這就意味著“表現”邏輯層現在要跨兩個物理層進行分割。
-
同樣,“數據訪問“邏輯層也并不是完全位于數據庫物理層,因為用于訪問和處理數據的命令(即 SQL)必須從數據庫層之外被生成和發送。這就意味著,與表現邏輯層一樣,數據訪問邏輯層代碼現在至少要跨兩個物理層進行分割。
這使我們認識到,盡管人們似乎很自然地認為表現邏輯層是在客戶機物理層上運行,而實際上這種情況僅存在于目前稱為“富客戶機”或“智能客戶機”的應用環境中。除此之外,“物理層”和“邏輯層”之間的聯系多半是偶然的,決不是從前認為的一對一的映射。
軟件設計邏輯分層背后的原理和原因是眾所周知的,并且在軟件體系結構領域已被普遍接受。(如果您不相信,或是想了解關于這一主題的詳細論述,請參閱 2006 年 8 月“MSDN 雜志”的“設計模式”專欄。該專欄詳細介紹了 Model-View-Presenter 模式,說明了將邏輯與用戶界面相分割的意圖和原因。)然而,物理分層仍然是一個見仁見智的討論話題;如果要將數據推到網絡中去,確保進行物理分層確實是十分必要的。
在某種程度上,要理解我們為什么至少需要兩個物理層是相當容易的,因為出于成本和數據集中化考慮,我們通常不希望將服務器級計算機放在用戶面前。但大多數關于 n 個物理層的討論中會提到第三個物理層,負責托管業務組件或邏輯;在規范的 Web 應用程序圖表中,有時還會出現第四個物理層,這四層分別是客戶端層、Web 服務器層、業務邏輯層和數據庫層。為什么是四個物理層?就這點而論,為什么要多于兩個物理層?
從歷史角度來說,有兩種力量相互結合催生了 n(物理)層方法。第一種是對可伸縮性的需求:隨著 Internet 的發展以及 Web 為越來越多的最終用戶所使用,企業意識到他們可以將企業系統推向個人客戶,將許多從前由內部系統(呼叫中心員工)所做的工作從公司轉移到 Web 上。例如,在 1980 年,客戶必須打電話給運輸公司,來向客戶服務代表詢問某件包裹到了哪里了。客戶服務代表會詢問跟蹤號碼,然后使用內部軟件系統來發現包裹的位置。而到了 2005 年,該客戶只需將所選 Web 瀏覽器指向運輸公司的 Web 站點,并輸入跟蹤號碼。使用相同的后端算法搜索同一后端數據存儲系統,而不同的是,現在信息直接由客戶輸入而不是通過內部員工間接輸入。但是,企業系統覆蓋范圍的擴大勢必伴隨著相應的成本,從前只有幾百名用戶(客戶服務代表)的內部系統,目前卻擁有幾十萬的潛在用戶(客戶)。這時我們會遇到一個瓶頸問題,大多數數據庫服務器可以支持幾百個并發的連接,然而并發連接如果達到幾十萬,很快就會使數據庫陷于癱瘓。
但結果是,人們發現了這些并發連接的一個有趣特性:對于大多數客戶機/服務器應用環境而言,針對數據庫所建立的連接大多數時間(95% 以上)都處于空閑狀態,來等待要針對數據庫所執行的請求。也就是說,瓶頸在于連接的數量,而不在于所執行的任務。這就說明,要增加數據庫的可伸縮性,我們需要以某種方式增加通過這些連接所完成的工作量。因此,我們創建了一個過渡層,客戶機通過連接該過渡層以多工方式向數據庫傳輸請求。簡單地說,如果數據庫只能支持 100 個連接,而每個客戶機連接被用去 1% 的時間,那么我們可以這樣來增加數據庫的可伸縮性:將 100 個客戶機連接到中間服務器,這個中間服務器僅使用 1 個連接(總共 100% 的時間,每個客戶端占 1%)來對數據庫進行操作。瞧,可伸縮性增加了一百倍。真不錯。
盡管如此,有多少應用環境真正需要這種可伸縮性呢?當然,在將企業應用環境帶到最終客戶群面前的情況下,這種可伸縮性可能時必要的。但許多應用環境(無論是否基于 Web)仍然是完全部署在內部的,這種情況下只有不到 100(有時少于 10)個客戶機將同時訪問系統。在內部小用戶群應用環境中還需要 n(物理)層方法嗎?
這時安全因素發揮了作用。對于運行在最終用戶計算機上的應用程序(基于 Web 或“富客戶機”),任何系統管理員或安全顧問都不可能推薦將包含關鍵任務數據的數據庫直接放在防火墻的后面(例如,從在安全范圍之外運行的計算機直接訪問)。如果加入一個中間計算機并將另一個防火墻置于其后,可以創建通常稱為隔離區或 DMZ 的區域,在其中可以進一步限制對數據庫的訪問。這樣一個 DMZ 極大地鞏固了安全基礎結構,降低了成功滲透的可能性。這不僅可以防止數據被竊取,而且還有助于保護服務器(及剩下的應用程序或系統)免受成功的拒絕服務攻擊。
使許多大型系統所有者青睞 n(物理)層系統的另一個因素是部署,即物理地將軟件放入客戶機所能訪問的計算機的過程。在傳統的客戶機/服務器環境中,業務邏輯與表現邏輯和數據訪問邏輯交織在一起,使編程人員感覺非常不舒服:每次需要新的更新時(例如需要更改企業對數據的處理方式或增加數據的新視圖),位于用戶桌面的“胖客戶機”就必須更換并/或加入新代碼。這就意味著,至少在這個時候,有人(通常是開發人員或系統管理員,兩者中級別較低的一個)需要在各計算機之間奔走,來安裝新代碼。或者是要求用戶從網絡下載最新的代碼。當然,大多數的用戶不是忽略了這一點就是不能正確操作。這兩種情況都不能使人們對頻繁發布這種明智之舉真正產生信任。而且部署是需要時間的,在這段時間內,系統必須暫停工作,以避免因混合版本的應用程序匆忙操作數據庫而造成的任何類型的語義數據損壞。
這一部署因素在很大程度上影響著人們對 n(物理)層模型,特別是對基于 Web 的應用程序的青睞程度。現在,人們無需再將代碼部署到各用戶桌面,而可以將其部署到(單個)Web 服務器,最終用戶的瀏覽器只需去選取這些更改,而這并不需要任何進一步的工作。就其本身而言,部署并不是鋪開 n(物理)層系統的原因;在傳統客戶機/服務器應用環境時代所無法獲得的一些備選方案現在已經加入可能部署方案清單中,這其中包括“無觸式部署”(在 .NET 1.x 中)和 ClickOnce(在 .NET 2.0 中),更不用說人們對 AJAX 和各種混合式結構日益濃厚的興趣。事實上,發布能在啟動時進行自我更新的富客戶機應用程序(如我們在 iTunes 軟件管理器、Windows Media Player,甚至是流行的 .NET 開發工具 Reflector 中所看到的)已變得越來越普遍。
采用 n 個物理層的第三個原因經常會被人們所提到,但往往卻不能真正實現,即中間物理層可以成為一些業務邏輯的集中點,這些邏輯可以由多個表現物理層訪問,卻不能為它們所知。關于這一點的典型例子就是組合式內聯網/外聯網應用環境,其中內部員工使用 WinForms(很快將升級為 Windows Presentation Foundation)應用程序來訪問中間層系統,中間層系統進而再訪問數據庫,而外部用戶(合作伙伴和/或客戶)使用 ASP.NET 或者可能是基于 SharePoint 的 Web 站點來進行同樣的操作:訪問中間層,中間層進而再訪問數據庫。
這個想法盡管在概念上似乎非常簡單,然而事實證明要從結構上來可靠地實現它是極其困難的。也因為這個原因,區分物理層和邏輯層越發顯得重要。如果在表現(邏輯)層、業務邏輯(邏輯)層和中間(物理)層之間有明確的區分,就可能將業務邏輯層嵌入客戶機(物理)層(如果是富客戶機應用前端)并通過避免網絡訪問來大大節約性能。
但是,設計在兩個不同(物理)層中使用的業務邏輯層是非常棘手的事情。這就意味著,業務邏輯(邏輯)層必須避免對于表現(邏輯)層或數據訪問(邏輯)層是否共同位于同一(物理)層做出任何假定,這樣一來就必須假定兩者都不位于其中。具體來說,在針對實際上運行于中間(物理)層服務器上的遠程業務對象執行數據綁定(通過 .NET Remoting)時,這足以毀掉一個應用程序。現在,每次屬性訪問和方法調用都是一次網絡遍歷,性能將會比…嗯…比構建出如此糟糕系統的結構設計師的信譽下降得還要快。
幸運的是,世界各地的結構設計師已經開始意識到“分布式對象”方法的危險性,現在時代的主旋律是“松散耦合”和“粗粒度通信”,而所有這些都需要以面向服務的結構體系方法的支持。與軟件開發的其他方面一樣,服務導向也有其自身的缺陷,但那是其他月份另一個專欄的話題。
作者簡介
Ted Neward 是致力于高級企業系統領域的獨立顧問,其客戶群包括從“財富”500 強企業到只有 10 名員工的小型企業的各種企業。他是 Java 和 .NET 技術方面的權威,尤其在 Java/.NET 集成(進程內和 Web 服務等集成工具方式)、后端企業軟件系統和虛擬機/執行引擎管道領域造詣頗深。
他自行或與他人合作編寫了《Effective Enterprise Java》(有效的企業 Java)、《C# In a Nutshell》(Nutshell 中的 C#)、《SSCLI Essentials》(SSCLI 精華)和《Server-Based Java Programming》(基于服務器的 Java 編程)等書籍,他同時也是一些技術期刊的特約撰稿人。Ted 還是 Microsoft 體系結構方面的 MVP、BEA 技術指導、INETA 講師、Pluralsight 培訓師、各種會議的發言人以及各種 JSR 的成員。他與妻子和兩個兒子共同居住在太平洋西北區,家中還有兩只貓和八臺 PC。
可通過 ted@tedneward.com 或訪問 Ted 的博客與他聯系。
轉載于:https://www.cnblogs.com/ChenZB/archive/2010/01/27/1657597.html
總結
以上是生活随笔為你收集整理的[转]实用体系结构:逻辑分层的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop Hbase适合存储哪类数据
- 下一篇: .NET 框架浅析