應用程序框架的概念幾乎是與面向對象技術同時出現的,它已被證明是縮短開發時間、提高組件重用性以及能及時適應市場情況變化的一個有效方法。應用程序框架將先進的底層技術(比如.NET Remoting、ADO.NET和安全性)封裝起來并提供用于程序開發的共用底層架構組件。應用程序開發小組能夠集中精力開發商業功能的原因是該框架提供了所有必要的底層架構組件。同時,由于框架鼓勵程序設計的一致性,因此你可以在應用程序的維護方面減少成本。
由于你的開發小組打算使用.NET技術進行開發,因此你會希望建立一個可靠的應用程序框架從而達到以一種節省成本的方式來使用這些性能的目的。在你這么做之前,了解有關程序管理及擴展性方面的問題是很重要的,你可以勾畫出一個面向service的應用程序框架來解決這些問題,從而在你的企業中提高開發者的生產力。
應用程序的可管理和可擴展性是任何開發機構中都會涉及到的兩個特殊問題。除非你一開始就把它們處理的很好,否則以后將會很難處理。首先,我將澄清可管理性和可擴展性的概念。一些程序組件(比如一個傳入數據庫連接字符串的組件)是需要一個配置文件來支持的。在你部署好這些組件之后,你可能需要在配置文件中添加新的條目或者對已有的條目進行修改。這種修改配置信息的能力和輕易地將它用在組件中的能力就說明你應用程序的可管理性很強。然而,在很多情況下,應用程序小組并沒有權利訪問產品服務器,因此需要服務器管理員來修改配置并重新啟動服務器。對應用程序開發小組來說,如果有能力修改特定程序的配置信息就更好了。
可擴展性指的是將新的、可管理的組件添加到框架中而不會導致已有軟件被改動的能力。通常你會用一系列的要求(比如數據庫訪問和安全性)來開始你底層架構的構建。當你想要添加新的性能時,(比如一個調度程序(scheduler)或者e-mail),你應該已經具備了一個作為這些組件的基礎的標準對象模式。同樣,你需要一個標準的方法來指定用于提供這些底層架構性能組件所使用的配置信息。
大多數應用程序框架主要用來為應用程序的開發提供一個模式,同時提高組件的重用性。為應用程序提供底層架構service是所有程序框架的主要功能目標,因此該框架中每個單獨部分的可擴展性和可管理性應該是首要目標。
識別Service
在開始討論架構問題之前,了解什么是service以及它是如何被應用于程序的框架中是非常重要的。不要將它們同Web services中的service混為一談。一個Service是可獨立管理的框架中的一個功能單元,每個service可能是運行的(started)和停止的(stopped),而且它有自己的配置信息。由于service有明確定義的界限,所以它們可以使好的系統更加鞏固并使該框架以最小可分離成員進行擴展。
應用程序框架為一致性程序開發提供大量的底部架構組件。應用程序框架提供的組件被分為兩類:工具組件(utility components)和service組件。我將主要介紹service組件,因此了解它們之間的區別是很重要的。
clearcase/" target="_blank" >cccc99>應用程序框架術語表 熟悉這些術語會方便你查找并為你的企業建立一個面向service的框架。 見下 |
應用程序框架術語表 熟悉這些術語會方便你查找并為你的企業建立一個面向service的框架:
|
比如說你有一個提供數據源(data-source)注冊功能的組件。這個組件提供連接字符串和一個列出所有數據源的XML配置文件。該組件在啟動時將文件加載到內存中并為數據源提供連接字符串。從該文件中加載配置是一個相當消耗內存的操作,因此你一定不希望在每次需要字符串的時候都新建這個組件。
設計平臺
面向service架構的目的是提供一個用于可識別的service開發模式以及一個對這些service提供運行支持的服務器。為了解釋它是如何運行的,我將概述一個范例場景。這個服務器是一個能夠接納(host)任何遠程對象的簡單程序。.NET中的Remoting是DCOM的替代品。它用來提供運行于不同應用程序域中的對象訪問,該訪問可以在同一個機器或不同機器中進行。由于可升級性(scalability)對于任何不平凡(nontrivial)的企業應用程序來說都是很重要的,因此你會希望將商務邏輯層從顯示層中分開。所有需要參與分布式事務處理的組件必須在COM+中被當作企業service來使用;所有其他組件被當作.NET遠程組件來使用。由于.NET不提供任何用于接納遠程組件的缺省容器程序,因此這個服務器正好填補了這個空缺。
![]() |
|
提供服務器
在這個例子中,服務器是一個簡單的Windows service,它為遠程對象提供一個主機環境(hosting environment)并使它們能夠在Transmission Control Protocol (TCP)通道中運行。服務器可以接納任何在配置文件中提到的remoting類。它注冊了一個名為Service Controller的內置遠程對象。該對象是這個框架的組成部分因為它控制著所有service的活動周期。在啟動時,Windows service會設置一個TCP通道,建立Service Controller對象,然后將它注冊為一個遠程對象。用戶端能夠通過一個名為Service Locator 的對象來訪問這些service,該對象是按照工廠方法(factory-method)的模式來設計的。這使得這些service和客戶端通過service實際位置(physical location)的封裝信息來形成松散耦合。和其他任何Windows service一樣,服務器可以通過控制面板來啟動或者停止。每次當你重新啟動這個服務器時,所有底層的service也會被重啟。在配置文件中的任何改動都會導致服務器的重新啟動。
在應用程序框架中,你可以將底層架構的功能單元(比如數據源管理器、安全管理器和e-mail發送器)作為service來實現。盡管它們具有不同的功能,但它們的概念都一樣——都是service。
![]() |
|
Service Controller提供了一些靈活的用法以便你想要使一個特殊的service臨時無效。它可以在一個service返回客戶端之前檢查它的狀態。在沒有控制器的情況下,services必須被注冊為遠程對象。在這種情況下,service對象甚至會在已經向客戶端發送出去之后被標注為無效,因為這個遠程主機(remoting host)無法中斷這個對service的請求。如果客戶端不檢查這個service的狀態,它可能會試著使用一些無效的對象。Service Controller在用于記帳操作(bookkeeping operation)中也非常有用,比如跟蹤發送到service的請求數和日志管理。
Service Locator提供了用于客戶端位置透明(location-transparent)的service訪問。你一定不想讓客戶端對象知道這些service的具體位置以及你用于訪問它們的技術是什么。如果客戶端了解了這些細節,客戶端和service之間就會形成緊密耦合(tightly coupled)。當形成緊密耦合之后,如果一個service從一個服務器移向了另一個服務器,那么你就需要改變所有的客戶端。你可以將執行信息集中放在Service Locator中。該類后面的XML配置文件會告訴你這個機器的名字,其中有哪些service在運行,以及在何種通道中運行(TCP或是HTTP)和端口數(port number)。為了使它的效率更高,你可以仿照該類的單實例模式,只讀取一次配置信息并確保該類在應用程序域中只有一個實例。一個GetService()方法會將service名作為參數并返回service對象。它會先和Service Locator的遠程對象取得聯系,然后調用控制器中的一個方法來得到被請求的service。
和其他Service進行聯系
service的范例還包括數據源注冊(data-source registry)、日志(logger)service和安全性service。數據源注冊service用來提供所有數據源的定義。這類信息主要位于諸如web.config等的程序配置信息中。這種方法存在兩個問題。首先,包含在配置文件中的用戶ID和密碼并不安全;第二,任何數據源都可能被幾個程序共用。因此最好將這些數據源信息(比如用戶名、用戶ID、密碼、服務器和數據庫)集中存儲,比如放入XML文件或者Active Directory (AD)中。數據源注冊service可以在啟動時讀取這些信息并把它們的定義傳遞給請求的應用程序。如果你在這個XML文件中添加了任何新的數據,可以很容易地重新啟動它。
日志service提供了一個集中的工具來記錄大量來自于應用程序的信息,它能夠幫你追蹤程序中的問題。這種集中的日志使你可以改變對程序進行日志記錄的級別(調試、警告、信息)。你可以利用一個名為log4net的open-source日志包來實現這個功能(見資源)。你可以實現一個適合該架構的service封裝器。
安全性service在用于提供驗證(authentication)和用戶授權方面是很有必要的。它可以通過AD來鑒別用戶并確認用戶是否有權訪問該應用程序。如果用戶被確認有權訪問,安全性service會讀取該用戶被授與的角色以及所有與該角色相關的許可信息。
實現一個service和其他service的通話是很有必要的。比如,如果你有一個將消息記錄到一個日志文件和數據庫中的日志service,你可能想要在所有的service 中使用它。你可以通過在初始化時將ServiceContext 對象傳入該service來激活這個通話連接。這個ServiceContext對象中包含一個名為GetService()的方法,它可以使用該service的名字并返回service對象。很重要的一點是所有這些service都運行于一個相同的處理過程和一個相同的應用程序域中。其結果是,service間的通話包含了簡單本地程序調用,不牽扯遠程。如果一個service在啟動時試圖使用其他的service,那么你就要保證XML配置文件中在該service之前列出了目標 service。
你可以在很多地方使用程序中的service,主要看這些service都提供了些什么功能,如果該service提供了一些可以用于顯示層的東西,就從顯示層中調用它。你可以從商務邏輯層中調用諸如信用卡處理的service。應用程序框架所提供的其他工具組件可以使用一些service,比如數據源注冊service。了解何時從一個程序中調用一個service是很重要的,它通過.NET Remoting來訪問,而不如本地程序調用那么快。你一定不想將架構中所有的組件都變成一個service。如果你的組件在啟動時不會消耗內存,那么它就不用變成一個service。
由于所有的service中都包含一些運行行為所依賴的配置信息,你可能需要修改這些信息,你還可能想要終止service而使它暫時無效或者重新啟動它。幸運的是,你可以用ASP.NET或者WinForm來建立一個service-manager應用程序,來提供執行這些功能的界面。由于這些配置信息是XML格式的,因此這個service-manager程序可以提供一個XML編輯工具來對這些配置進行修改。配置信息由控制器在啟動時加載,所以你可以在內存中修改它,并在需要時將它保存到XML文件中。Service管理器還能夠提供一個開始和停止service的工具。如果你將它作為一個ASP.NET程序進行開發,你可以通過瀏覽器來對所有的service進行配置,而無需在操作系統層訪問服務器。
企業應用程序的開發是相當復雜的,因此你一定不想草率地開始每個.NET程序的開發。你可以通過花些時間和精力開發出一個好的應用程序框架來提高開發人員的生產力。
一個面向service的架構可以提高應用程序底層架構的可管理性和可擴展性。其中包括一個作為容器的Remoting Server,它為所有service提供運行支持。所有長時間的初始化操作在該容器中都被當作service來使用。Service Locator用于提供位置透明性來訪問所有客戶端的service。
這個用于面向service框架的Unified Modeling Language(UML)設計模式顯示了所有框架的概念以及它們如何在結構上彼此關連。RemoteServer是一個Windows service,它用于接納remoting ServiceController對象。ServiceController控制著所有service的活動周期。ServiceContext為每個service提供聯系??蛻舳送ㄟ^ServiceLocator來訪問service。
原文轉自:http://www.anti-gravitydesign.com