摘 要:通過研究通信軟件中常用的設(shè)計(jì)算法,收集使用面向?qū)ο蠹夹g(shù)開發(fā)通信軟件時(shí)常用的設(shè)計(jì)模式,利用Java語言完成基于Java的通信中間件設(shè)計(jì)與實(shí)現(xiàn),并給出了主要部分的實(shí)現(xiàn)。實(shí)現(xiàn)了全部的JMS標(biāo)準(zhǔn)API,提供了消息持久化、消息預(yù)覽和消息選擇功能,建立了可靠的線級(jí)通訊連接,提高了產(chǎn)品的服務(wù)質(zhì)量。
關(guān)鍵詞:面向?qū)ο蠹夹g(shù); Java通信中間件; 通信軟件; 對象序列化
中圖分類號(hào):TP31文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1004-373X(2010)15-0149-04
Design and Implementation of JAVA-based Middleware for Communication
YIN Feng-she,JIAO Lei
(Shaanxi Polytechnic Institute, Xianyang 712000, China)
Abstract: The design and implementation of JAVA-based communication middleware were achieved with JAVA language by studying the common design algorithms of communication softwares and collecting the design patterns of using the object-oriented technology to develop communication software. All the JMS APIs were implemented. The reliable wire-level communication was established. The implementation process of the major parts is presented. The functions of persistent messaging, message preview and message selection are provided. The service quality of the product is improved.
Keywords: object-oriented technology; Java-based communication middleware; communication software; object serialization
1 總體設(shè)計(jì)
通信中間件[1]目前并無標(biāo)準(zhǔn)可循,一般把工業(yè)標(biāo)準(zhǔn)TCP/IP協(xié)議作為基礎(chǔ),遵循X/Open的分布式計(jì)算環(huán)境需求多樣化、用戶數(shù)目規(guī)?;?、業(yè)務(wù)邏輯復(fù)雜化的發(fā)展要求,實(shí)現(xiàn)消息位置無關(guān)性、用戶透明性。應(yīng)用程序使用通信中間件提供的通信服務(wù),遵循中間件提供的通信協(xié)議進(jìn)行相互間的通信。解除應(yīng)用程序和通信介質(zhì)(或網(wǎng)絡(luò))以及遠(yuǎn)程應(yīng)用程序之間的偶合。
本文所述的通信中間件采用集中式的通信方式。其設(shè)計(jì)思路來源于中間件模式[2]。結(jié)構(gòu)如圖1所示。
圖1 通信中間件結(jié)構(gòu)圖
通信中間件由一個(gè)消息網(wǎng)關(guān)和多個(gè)Agent組成。消息網(wǎng)關(guān)是系統(tǒng)的核心,它完成消息轉(zhuǎn)發(fā)功能。為了保證通信的可靠性,消息網(wǎng)關(guān)與Agent的通信基于TCP協(xié)議。為了提高端到端通信的QoS,在消息網(wǎng)關(guān)中引入了并發(fā)處理,這樣可以防止因?yàn)榱髁靠刂圃斐傻淖枞却龑π阅艿挠绊憽?/p>
Agent位于每個(gè)通信進(jìn)程內(nèi)部,向上層應(yīng)用提供統(tǒng)一的通信接口,屏蔽通信細(xì)節(jié)。Agent為上層應(yīng)用模塊提供了兩種不同的接口[3]:同步通信接口和異步通信接口。
一個(gè)設(shè)計(jì)良好的通信中間件因該具有良好的可移植性、可擴(kuò)展性和可復(fù)用性,同時(shí)還要保持高效率和使用方便等特點(diǎn)。面向?qū)ο蠹夹g(shù)是開發(fā)它的理想工具。
2 開發(fā)工具介紹
本系統(tǒng)的開發(fā),使用了Java提供的許多工具[4],他們包括:
2.1 多線程支持
“線程”是進(jìn)程內(nèi)部單一的一個(gè)順序控制流,一個(gè)進(jìn)程可能容納了多個(gè)同時(shí)執(zhí)行的線程。多線程的應(yīng)用范圍很廣。當(dāng)程序的一些部分同特定的事件或資源聯(lián)系在一起,同時(shí)又不想為它而暫停程序其他部分的執(zhí)行??煽紤]創(chuàng)建一個(gè)線程,令其與那個(gè)事件或資源關(guān)聯(lián)到一起,并讓它獨(dú)立于主程序運(yùn)行。
Java提供了一套內(nèi)建的機(jī)制,提供對多線程的支持。為創(chuàng)建一個(gè)線程,最簡單的方法就是從Thread類繼承。這個(gè)類包含了創(chuàng)建和運(yùn)行線程所需的一切東西。Thread最重要的方法是run(),它包含那些會(huì)與程序中的其他線程“并發(fā)”或“同時(shí)”執(zhí)行的代碼。通過對其進(jìn)行過載或者覆蓋,使其能充分按自己的吩咐行事。通過實(shí)現(xiàn)Runnable接口也可以將一個(gè)類改造成線程。
在本系統(tǒng)中,為了提高系統(tǒng)的運(yùn)行效率和并發(fā)處理能力以及阻塞通信方式的使用,大量的采用了多線程的實(shí)現(xiàn)。Agent中的消息分發(fā)器采用了單獨(dú)的線程實(shí)現(xiàn)。Reactor中引入了線程池對收到的消息的并發(fā)處理。Gateway中的消息接收和消息發(fā)送功能都是采用單獨(dú)線程實(shí)現(xiàn)。
2.2 對象序列化處理
對象序列化(Object Serialization)面向那些實(shí)現(xiàn)了Serializable接口的對象,將它們轉(zhuǎn)換成一系列字節(jié),并可在以后完全恢復(fù)回原來的樣子。這一過程亦可通過網(wǎng)絡(luò)進(jìn)行。本系統(tǒng)內(nèi)部,網(wǎng)關(guān)和Agent之間傳遞消息,采用了序列化機(jī)制,將消息封裝成對象,利用Java的序列化機(jī)制直接傳送對象,簡化上層應(yīng)用對消息的封裝與解析。
2.3 通信對象
Java庫的I/O類[5]分為輸入與輸出兩個(gè)部分。輸入、輸出的源地和目的地包括(每個(gè)都有一個(gè)相關(guān)的InputStream子類):字節(jié)數(shù)組、String對象、文件、管道、一系列其他以及Internet連接等。與輸入有關(guān)的所有類都從InputStream繼承,而與輸出有關(guān)的所有類都從OutputStream繼承。Java的I/O類庫采用的是分層的設(shè)計(jì)原則,InputStream、OutputStream類以及它們的子類處于底層,一般的I/O操作很少直接使用它們,一般都使用建立在它們上的裝飾器類將多個(gè)對象重疊在一起,提供自己期望的功能。對于序列化對象的I/O,Java提供了裝飾器類ObjectInputStream和ObjectOutputStream。
3 Gateway的設(shè)計(jì)與實(shí)現(xiàn)
Gateway是通信系統(tǒng)中的中間件,它消除了各個(gè)通信端點(diǎn)之間的緊偶合,提高了整個(gè)通信系統(tǒng)的靈活性。它實(shí)現(xiàn)為一個(gè)單獨(dú)的進(jìn)程,在應(yīng)用系統(tǒng)運(yùn)行過程中始終保持運(yùn)行狀態(tài)。
3.1 功能結(jié)構(gòu)設(shè)計(jì)
Gateway的功能結(jié)構(gòu)如圖2所示。通過分離輸入和輸出功能,減少他們之間以及多個(gè)不同的通信連接之間的相互影響,提供了對不同的輸入和輸出使用不同的并發(fā)策略的可能性。整個(gè)消息的傳遞過程可以分為三個(gè)階段:輸入處理階段、路由選擇階段和輸出處理階段。
圖2 網(wǎng)關(guān)功能結(jié)構(gòu)圖
消息接收功能與Agent通信,接收Agent發(fā)來的消息,并將消息送給消息發(fā)送功能;路由功能完成路由選擇;消息發(fā)送功能接收待發(fā)送的消息,將它們發(fā)往目的Agent,發(fā)送功能內(nèi)部維護(hù)一個(gè)消息發(fā)送隊(duì)列,實(shí)現(xiàn)流量控制;監(jiān)視功能監(jiān)視發(fā)送和接收功能,及時(shí)釋放無用的通信資源。
3.2 Gateway的實(shí)現(xiàn)
3.2.1 靜態(tài)結(jié)構(gòu)
網(wǎng)關(guān)實(shí)現(xiàn)為一個(gè)單獨(dú)運(yùn)行的進(jìn)程,為了提高運(yùn)行效率,它的內(nèi)部采用多線程方式,實(shí)現(xiàn)并發(fā)處理。類圖表現(xiàn)了網(wǎng)關(guān)的靜態(tài)組成結(jié)構(gòu)。類圖如圖3所示。
圖3 Gateway的類圖
類Gateway是網(wǎng)關(guān)進(jìn)程的入口。main()方法啟動(dòng)Gateway,完成Gateway的初始化配置[6]。實(shí)現(xiàn)如下:
public static void main(String[] args) {
……
Factory factory = Factory.getInstance(); /*獲取Factory 的全局惟一實(shí)例*/
Timer
run()
timestart()
timestop()
……
factory.make_monitor(); /* 啟動(dòng)后臺(tái)監(jiān)視線程 */
factory.make_routetable(); /*創(chuàng)建路由表 */
factory.make_acceptor_handler(); /* 打開通信端口,接收Agent 的連接請求*/
……
}
類SvcHandler,AcceptorHandler和RegisterHandler實(shí)現(xiàn)了同步的Acceptor模式。類AcceptorHandler接收Agent的連接請求,完成連接初始化工作。類RegisterHandler完成服務(wù)初始化,認(rèn)證Agent的合法性,對于合法的Agent,建立通信結(jié)構(gòu)Commstruture并在路由表中增加相應(yīng)的記錄。
3.2.2 動(dòng)態(tài)結(jié)構(gòu)
網(wǎng)關(guān)的實(shí)現(xiàn)充分地利用了Java的多線程機(jī)制[7],組成網(wǎng)關(guān)的類通過繼承Thread類,實(shí)現(xiàn)為線程,在運(yùn)行時(shí)可以并發(fā)的運(yùn)行。運(yùn)行中的網(wǎng)關(guān)包括多個(gè)線程。這些類包括:Monitor,AcceptorHandler,RegisterHandler,Sender和Receiver。Monitor和AcceptorHandler線程有著和網(wǎng)關(guān)進(jìn)程一樣的生存期,網(wǎng)關(guān)啟動(dòng)后立刻被啟動(dòng),網(wǎng)關(guān)退出時(shí)被殺死。AcceptorHandler阻塞等待,直到收到某個(gè)Agent發(fā)來的連接請求,啟動(dòng)一個(gè)RegisterHandler線程處理該請求。RegisterHanler線程驗(yàn)證請求連接的Agent的合法性,接收合法的Agent的連接請求,建立并保存與之通信的通信結(jié)構(gòu),處理完畢后RegisterHandler線程死掉。與Agent通信的通信結(jié)構(gòu)中包括兩個(gè)線程:Sender和Receiver,在與對應(yīng)的Agent通信有效期內(nèi)生存。
4 Agent的設(shè)計(jì)與實(shí)現(xiàn)
Agent扮演著兩種不同的角色:在和網(wǎng)關(guān)通信過程中它是客戶端;在應(yīng)用模塊看來它是底層通信系統(tǒng)的惟一代表。應(yīng)用模塊通過Agent訪問本系統(tǒng)。Agent為應(yīng)用進(jìn)程管理通信資源,完成通信并發(fā)控制,為上層應(yīng)用模塊屏蔽了復(fù)雜的通信資源管理和并發(fā)控制問題。
4.1 通信接口設(shè)計(jì)
通信中間件向上層提供面向連接的通信服務(wù)。有一系列通信調(diào)用接口,包括連接初始化/關(guān)閉接口和消息發(fā)送/接收接口。消息傳送有異步發(fā)送、同步發(fā)送和通知消息發(fā)送接口三種方式。
4.2 功能結(jié)構(gòu)設(shè)計(jì)
Agent的功能結(jié)構(gòu)如圖4所示。
消息發(fā)送功能負(fù)責(zé)將應(yīng)用模塊提交的消息發(fā)送給網(wǎng)關(guān)。消息接收功能接收網(wǎng)關(guān)發(fā)來的消息,交給控制模塊,判斷消息的類型,如果是同步通信的應(yīng)答消息,將該消息返回給調(diào)用者。否則,由控制功能將該消息送交由應(yīng)用模塊定制的消息處理功能進(jìn)行處理。
圖4 Agent功能結(jié)構(gòu)圖
4.3 Agent的實(shí)現(xiàn)
4.3.1 模式結(jié)構(gòu)圖
Agent的設(shè)計(jì)采用了如圖5所示的模式。
圖5 Agent模式結(jié)構(gòu)圖
4.3.2 類圖
Agent的類圖如圖6所示。
圖6 Agent的類圖
類Connector,Svc_Handler,Svc_Handler_Register實(shí)現(xiàn)了同步方式的Connector模式,完成和網(wǎng)關(guān)建立主動(dòng)連接。在這里使用Connector模式的目的和Gateway中使用Acceptor的目的一樣,都是解耦通信初始化和服務(wù)初始化。
類Reactor,Message Handler,Concrete Message Handler,Message Multiplexer,Thread Message Process,Message Queue_Asyn,Message Queue_Syn實(shí)現(xiàn)了Reactor模式,完成異步消息觸發(fā)處理。
5 消息的設(shè)計(jì)與實(shí)現(xiàn)
本系統(tǒng)是基于消息傳遞[8]的通信中間件。為了簡化應(yīng)用模塊對消息的封裝與解析。利用Java的序列化機(jī)制,將消息封裝成對象,通過網(wǎng)絡(luò)直接傳送消息對象。消息由消息頭和消息體組成,消息頭包括消息的類型(控制消息或數(shù)據(jù)消息),消息體包含消息的具體類型和消息內(nèi)容。Message類為通信過程中消息的處理提供了統(tǒng)一的接口。
/*消息類*/
Class Message implements Serializable{
int type;/*消息的類型:控制消息或數(shù)據(jù)消息*/
MessageBody msgBody; /*消息體*/
}
/*消息體的基類*/
Class MessageBody implements Serializable{
int type;/*消息的具體類型*/
}
/*控制消息消息體*/
Class ControMessage extends MessageBody implements
Serializable{
Object msgvalue /*消息內(nèi)容*/
}
/*數(shù)據(jù)消息消息體*/
Class DataMessage extends MessageBody implements
Serializable{
String dstid; /*目的進(jìn)程標(biāo)識(shí)*/
String srcid; /*源進(jìn)程標(biāo)識(shí)*/
Object msgvalue /*消息內(nèi)容*/
}
6 結(jié) 語
隨著分布式應(yīng)用系統(tǒng)的迅速發(fā)展,通信中間件作為開發(fā)分布式應(yīng)用的支持系統(tǒng)有很大的發(fā)展,特別是隨著面向?qū)ο蠹夹g(shù)的日益成熟,采用面向?qū)ο蠹夹g(shù)開發(fā)通信中間件的需求越來越大。本系統(tǒng)應(yīng)用于項(xiàng)目“基于Java的網(wǎng)絡(luò)計(jì)費(fèi)管理系統(tǒng)”中,作為低層通信支持系統(tǒng),取得了良好的效果。
參考文獻(xiàn)
[1]常煜芬,張育平.中間件技術(shù)研究[J].計(jì)算機(jī)應(yīng)用研究,2001,18(10):21-23.
[2]BAKKEN David E. Middleware[M]. Washington: State University, 2002.
[3]ATTOUR A. An oriented model for parallel and reactive systems[J]. Proc. IEEE CS 12th Real-time Systems Symp., 2008, 49(10): 69-72.
[4]ECKEL Bruce. Java編程思想[M].北京:機(jī)械工業(yè)出版社,1999.
[5]HORSTMANN Cay S, CORNELL Gary. Java 2核心技術(shù)卷Ⅱ:高級(jí)特性[M].陳昊鵬,王浩,姚建平,譯.北京:機(jī)械工業(yè)出版社,2000.
[6]SCHMIDT Douglas C. Design patterns for initializing network services: introducing the acceptor and connector patterns[J]. C++ Report, 2006, 8: 217-219.
[7]SCHMIDT Douglas C. The object-oriented design and implementation of the Reactor: A C++ wrapper for UNIX I/O multiplexing[J]. C++ Report, 2003, 5: 113-117.
[8]李立宏,李浩昱,張福恩.消息中間件的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)工程,2000,26(1):46-48.
[9]王繼成,孫穎.www文檔協(xié)同寫作系統(tǒng)中通信中間件的設(shè)計(jì)與實(shí)現(xiàn)[J].小型微型計(jì)算機(jī)系統(tǒng),1999,20(4):266-269.
[10]O′RYAN Pyarali I C. Using principle patterns to optimize real-time ORBs[J]. Concurrency Magazine, 2000, 8(1): 151-173.