(武夷學院數學與計算機系,福建 武夷山354300)
在分布式應用系統開發中,基于面向服務體系架構(Service-Oriented Architecture,SOA)的軟件架構已經成為主流。JavaRMI、EJB、CORBA(Common Object Request Broker Architecture,公共對象請求代理體系結構)和Microsoft的 WCF(Windows Communication Foundation,視窗通信基礎)、.NET Remoting、Web Service等都可以用于SOA系統的開發[1-5]。以上技術作為成熟的機制,經過層層包裝,隱藏了技術細節,在方便開發人員使用的同時,也存在一個問題:開發人員知道如何使用框架進行開發,但無法理解框架原理及底層運作細節,對于一些特殊的編程需求,難以對框架進行有效擴展。為此,筆者提出了一種基于Proxy模式的遠程處理框架,其在局域網的應用中編程模型簡單,框架原理易于理解,且能夠實現高速有效的遠程方法調用。
Proxy模式有助于跨越障礙進行數據訪問[6]。Proxy模式的意圖是為其他對象提供一種代理以控制對這個對象的訪問[7]。其適用場合之一就是遠程代理(Remote Proxy)模式。遠程代理為一個對象在不同的地址空間提供局部代表,隱藏了一個對象存在于不同地址空間的事實。Proxy模式的結構如圖1所示,其參與者中,Proxy對象保存一個引用使得代理可以訪問實體RealSubject對象。若為遠程代理,則Proxy對象負責對請求及其參數進行編碼,并向不同地址空間中的實體發送已編碼的請求。

圖1 Proxy模式結構
遠程處理框架從功能上應當使跨應用程序邊界(可以跨應用程序域、跨進程、跨機器乃至跨網絡)的應用程序之間能夠進行通信。為便于敘述,將參與通信的應用程序區分為客戶端和服務器端。通過遠程處理框架,客戶端能夠以與調用本地方法相同的方式調用服務器端的遠程服務對象的方法。筆者提出的遠程處理框架包含代理和遠程處理2個組件,其結構如圖2所示。

圖2 基于Proxy模式的遠程處理框架
通過使用代理組件,客戶端獲得TransparentProxy(透明代理),TransparentProxy調用RealProxy(真實代理)的Invoke方法,所以,重寫Invoke方法是創建代理對象的關鍵。Invoke方法應當包括:向服務器發出鏈接請求;將調用請求封裝成消息,向服務器發送該消息;等待并接收返回消息;將消息返回代理對象。因透明代理與遠程服務對象類型一致,故客戶端調用代理上的方法與調用遠程服務對象的方法相同。
現有的各類遠程處理框架中,服務器一般充當宿主,即只發布遠程服務對象,其余的工作都由遠程處理框架完成。框架中的遠程處理組件遵循此原則,其功能包括監聽客戶端鏈接請求、根據客戶端的調用請求調用服務對象的方法、將方法調用的結果發送回客戶端的代理對象等。
筆者所提出的遠程處理框架采用Remote Proxy模式,由代理組件和遠程處理組件構成。代理組件ProxyClass從抽象類RealProxy派生,其通過持有遠程服務接口IServerClass可在客戶端中以本地化的方式調用遠程服務對象的相關方法;遠程處理組件發布遠程服務對象,并通過Socket監聽來自客戶端的鏈接請求,根據請求內容進行方法調用并返回處理結果。
Remote Proxy模式與傳統Proxy模式最大的區別在于代理類ProxyClass沒有實現公共接口IServerClass,而是派生于RealProxy類(見圖3)。RealProxy是.NET框架提供的用于實現代理功能的抽象類,其包括抽象方法Invoke,Invoke方法定義如下:
public abstract IMessage Invoke(IMessage msg);
其中,類型為IMessage的參數msg包含了有關方法調用的信息:對象標識、方法名和參數列表等。RealProxy通過Invoke方法持有遠程服務接口的信息。ProxyClass因派生于RealProxy而獲得了遠程服務接口,并通過Invoke方法實現了Remote Proxy模式的意圖:對方法調用請求信息進行編碼,并向不同地址空間中的實體發送已編碼的請求[6]。

圖4 遠程處理框架通信流程
代理組件是遠程處理框架中應用于客戶端的重要組件,客戶端通過代理組件實現方法調用消息的封裝、傳輸,并接收遠程服務對象調用結果的返回消息(見圖4)。
創建任何代理類都必須繼承于抽象類RealProxy[7]。為了獲取遠程對象的透明代理,可通過調用代理類的GetTransparentProxy方法。用透明代理對象調用遠程對象的方法時,將自動調用被重寫過的Invoke方法。重寫Invoke方法的主要步驟如下:①生成遠程對象方法的調用消息。以下代碼中,RemoteMethodInfo類是自定義的,用于表示遠程對象方法的調用消息:

②將調用消息序列化到內存流。這里需要用到MemoryStream類,該類定義的流對象可以將對象狀態序列化到內存中。③與發布遠程對象的服務器建立鏈接。用TcpClient類的構造函數進行到服務器的鏈接,此處需提供主機名和端口號。④將步驟②處理結果發送到服務器。TcpClient類的GetStream方法返回一個NetworkSteam類對象,該對象用于對Internet中的數據進行發送或接收。⑤等待服務器響應。DataAvailable屬性用于確定是否可以讀取數據,如果可以在NetworkSteam上讀取數據,則為true,否則為false。⑥從服務器接收數據。當服務器將調用結果返回時,將流上的數據讀取到字節數組_buffer中,并用其構建內存流對象,最后將接收到的數據反序列化以重構對象。⑦根據調用結果構造返回消息。構造返回消息就是創建ReturnMessage對象,該對象將被RealProxy類的其他方法解包裝,獲得真正的調用結果。
遠程處理組件是遠程處理框架的核心,服務器端使用遠程處理組件注冊信道,發布遠程服務對象,并處理來自客戶端的調用請求[8]。遠程處理組件結構如圖5所示,其中RegisterChannel方法實現信道注冊功能,Register RemoteObject方法實現遠程服務對象注冊功能,StartServers方法對每個注冊信道啟動一個線程進行處理,ChanelProc方法具體負責與客戶端的通信,MyChannel和MyRemoteObj是自定義類,分別代表信道對象和遠程服務對象。

圖5 遠程服務組件結構
1)信道注冊功能 服務器注冊信道時,為每個信道命名。信道注冊方法中,首先檢測信道名稱,若信道名稱不存在,則創建信道并分配端口號,將該信道添加到已注冊的信道集合中。
2)遠程服務對象注冊功能 服務器注冊遠程對象時,為每個遠程對象指定一個URI。遠程對象注冊方法中,首先檢測該URI是否已存在,若該URI不存在,則注冊該遠程對象并將其添加到已注冊的遠程對象集合中。
3)啟動注冊信道 對于每一個已注冊的信道啟動一個線程池,利用QueueUserWorkItem方法將信道監聽處理方法ChannelProc作為回調方法排入隊列等待執行,channel對象作為參數傳遞給ChannelProc方法。
4)信道處理方法 信道處理方法首先啟動監聽。利用Socket對象接收客戶端連接請求,并通過序列化和反射機制,用所接收的數據創建遠程服務對象,調用對應方法,獲取結果,反序列化后發送回客戶端[8]。其詳細步驟如下:①接收用戶請求,AcceptSocket方法用于接收來自客戶端的連接請求,并返回一個Socket對象;②接收并緩存數據,Receive方法接收客戶端的請求數據,并將所接收數據存入到緩沖區Buffer中;③將數據反序列化為調用請求對象;④獲取遠程服務對象標識;⑤獲取實際的遠程服務對象,ActiveObj是MyRemoteObj中定義的只讀屬性,其通過反射機制創建了遠程服務對象;⑥調用遠程對象的相應方法并獲得結果;⑦將調用結果序列化并發送到客戶端。
為驗證以上遠程處理框架的有效性,將框架相關組件應用于高校大學生素質拓展學分管理系統。部分高校要求學生需積極參加各類課外活動以獲取素質拓展學分,學分類型分為學術活動、文體活動等6類,規定每類需修滿1學分,總分不低于10學分方可畢業。一般情況下,每位學生的學分驗證信息約60~100條,每學期增加的信息記錄約10萬條。系統共有學生、院系教務管理人員和校素質拓展中心管理人員3類用戶:學生通過瀏覽器登錄系統,可提交學分驗證信息和查看本人學分,院系教務管理人員通過客戶端登錄遠程服務器,審核信息并提交數據。系統用C#語言開發,用SQLServer2005作為數據庫服務器。下面以院系教務管理人員遠程登錄為例,相關組件部署如表1所示。

表1 遠程處理框架組件及部署
為便于部署,將服務接口與服務類分放在2個不同的文件中,客戶端只需持有服務接口即可。這樣設計的優勢很明顯,只要接口不變,服務類的具體實現的變化就不會對客戶端產生影響,保證了客戶端的穩定性(IServerClass聲明了服務接口,ServerClass實現IServerClass(見圖3))。其中Authentication方法對教務管理人員提供的UID和密碼進行驗證并返回驗證結果。
通常,在遠程處理框架中,服務器端一般是作為遠程服務對象的宿主程序。服務器端通過以下步驟發布遠程服務對象:使用遠程處理組件,先注冊一個信道,再注冊一個遠程服務對象,之后,利用線程池接受客戶端的服務調用請求并進行處理。代碼如下:

客戶端通過代理組件獲取遠程服務對象的透明代理后,將以使用本地對象的方式使用遠程服務對象。院系教務管理人員在進行素質拓展學分的管理前需登錄到服務器進行身份驗證,方法如下:

研究了一種遠程處理框架,通過Remote Proxy模式將框架分解成代理組件和遠程處理組件,在組件設計中,涉及序列化機制、反射機制等.NET框架中的重要技術,并基于Socket實現了遠程服務對象方法調用信息的網絡通信過程。最后,將其應用于高校大學生素質拓展學分管理系統,客戶端通過代理組件能夠以調用本地對象成員函數的方式調用遠程服務對象的函數。當然,與成熟的分布式系統構建技術相比,筆者所提出的框架還有其不足之處,如發布對象的宿主機制還不夠完善,無法采用配置文件等。
[1]李海聞,寧敏,林福良,等 .一種基于CORBA的分布式應用模型 [J].計算機系統應用,2010,19(2):33-34.
[2]劉丹,程曉,侯德林 .一種基于RMI的分布式架構設計 [J].計算機應用與軟件,2007,24(9):207-208.
[3]鐘涵,李志蜀,王汾雁,等..NET Remoting和Web Service結合的分布式應用設計與實現 [J].計算機應用,2007,27(6):213-214.
[4]趙慶霞,孫建伶 .基于WCF的服務緩存設計與研究 [J].計算機工程與設計,2010,31(14):3151-3152.
[5]Lowy J.WCF服務編程 [M].張逸,徐寧 譯 .北京:機械工業出版社,2008:14-16.
[6]Martin R C,Martin M.敏捷軟件開發:原則、模式與實踐(C#版)[M].鄧輝,孟巖 譯 .北京:人民郵電出版社,2008:377-381.
[7]Gamma E,Helm R,Johnson R,et al.Design patterns elements of reusable object-oriented software [M].New York:Adison-Wesley,1995:233-234.
[8]飛思科技產品研發中心 .精通.NET核心技術——高級特性 [M].北京:電子工業出版社,2002:202-211.