王偉平 楊思勤
[摘要]隨著J2EE技術(shù)在企業(yè)級平臺系統(tǒng)中的廣泛應(yīng)用,用戶對基于JAVA的網(wǎng)絡(luò)服務(wù)器程序的性能與擴(kuò)展性提出更高的要求。圍繞服務(wù)器模型中高效NIO實現(xiàn)與高擴(kuò)展性架構(gòu)兩方面介紹一個網(wǎng)絡(luò)應(yīng)用服務(wù)器模型,結(jié)合實際應(yīng)用環(huán)境對這種模型的特點及優(yōu)越性進(jìn)行說明,并指出進(jìn)一步的研究方向。
[關(guān)鍵詞]JAVA NIO 業(yè)務(wù)擴(kuò)展
中圖分類號:TP3文獻(xiàn)標(biāo)識碼:A文章編號:1671-7597(2009)0910012-02
一、引言
J2EE是一種利用Java2平臺來簡化企業(yè)解決方案的開發(fā)、部署和管理相關(guān)的復(fù)雜問題的體系結(jié)構(gòu)。在保留現(xiàn)存的IT資產(chǎn),快速開發(fā)以及支持異構(gòu)環(huán)境等因素的考慮下,眾多大型企業(yè)的企業(yè)級應(yīng)用均采用J2EE技術(shù)。在大型的企業(yè)架構(gòu)中,基于客戶/服務(wù)器模式所設(shè)計的服務(wù)器程序由于能為客戶提供一些特定的服務(wù)而得到了普遍的應(yīng)用,這種服務(wù)器程序的核心技術(shù)是并發(fā)技術(shù),服務(wù)器需要同時對多個客戶請求提供服務(wù)[1],為每個連接的客戶都分配一個線程來處理輸入輸出,其線程與客戶機(jī)之比幾乎為1:1,因此,應(yīng)用服務(wù)器易受到大量線程開銷的影響,導(dǎo)致了性能低下又缺乏可伸縮性。為了解決這個問題,java平臺的開發(fā)者引入了非阻塞I/O機(jī)制(NIO)[2]。NIO與IO包提供的阻塞模型不同,NIO在對一個非阻塞的連接進(jìn)行操作時,調(diào)用會立即返回,而不是掛起等待,這就使得一個線程管理多個連接成為可能,從而使資源使用率得到很大的提升[3]。
在滿足高性能需求同時,企業(yè)還要求服務(wù)器端平臺能提供可伸縮性來滿足大量的新客戶,為了解決當(dāng)前企業(yè)應(yīng)用的迫切需求,我們需要一種基于NIO技術(shù)的兼顧高效并發(fā)與業(yè)務(wù)擴(kuò)展兩方面的服務(wù)器模型。
二、研究現(xiàn)狀
JDK1.4提供的無阻塞I/O(NIO)有效解決了多線程服務(wù)器存在的線程開銷問題,在NIO中使用多線程,主要目的已不是為了應(yīng)對每個客戶端請求而分配獨立的服務(wù)線程,而是通過多線程充分利用多個CPU的處理能力,減少處理時間,達(dá)到提高服務(wù)能力的目的。許多基于NIO的多線程服務(wù)器程序往往直接用基于選擇器(Selector)的Reactor模式實現(xiàn),這種簡單的事件機(jī)制對于較復(fù)雜的服務(wù)器應(yīng)用,顯然缺乏擴(kuò)展性和可維護(hù)性,而且缺乏直觀清晰的結(jié)構(gòu)層次[4]。
文獻(xiàn)[4]針對上述問題提出了基于事件回調(diào)思想下的NIO多線程服務(wù)器,但該服務(wù)器設(shè)計的運行時Socket分發(fā)機(jī)制無法正常的對SocketChannel
(套接字通道)進(jìn)行處理。文獻(xiàn)[4]設(shè)計將新接收的客戶端通道放在連接接收線程中進(jìn)行select,當(dāng)客戶端有數(shù)據(jù)到達(dá)時,socket被分配給了處理線程。在任意給定時刻最多只能有一個線程對SocketChannel進(jìn)行讀取和寫入操作[5],而客戶端數(shù)據(jù)到達(dá)時連接接收線程仍然在對SocketChannel進(jìn)行select,導(dǎo)致了連接接收線程與處理線程對客戶端SocketChannel的訪問發(fā)生沖突。本文提出的使用多線程套接字分發(fā)機(jī)制的改良NIO模型很好地解決上述諸多問題。
在具備清晰的層次與高效的性能的同時,服務(wù)器的運算邏輯組織方式是決定服務(wù)器擴(kuò)展性的主要因素。例如一個網(wǎng)絡(luò)服務(wù)器需要向手持PDA終端提供采集數(shù)據(jù)處理服務(wù),當(dāng)出現(xiàn)不同接口協(xié)議的PDA終端時,服務(wù)器必須對新協(xié)議進(jìn)行支持。在服務(wù)器開發(fā)設(shè)計過程中往往只重視服務(wù)器的性能而忽視了服務(wù)器的再編程能力,這導(dǎo)致某一種特殊應(yīng)用的網(wǎng)絡(luò)服務(wù)器擴(kuò)展性較低或是擴(kuò)展難度較大。本文使用改良NIO模型的事件回調(diào)機(jī)制為接口,以NIO模型的線程池業(yè)務(wù)數(shù)據(jù)擴(kuò)展框架的運行載體,構(gòu)建了一個網(wǎng)絡(luò)應(yīng)用服務(wù)器模型,提供了一個具備高效性與擴(kuò)展性的服務(wù)器開發(fā)模型解決方案。
三、多線程套接字分發(fā)NIO模型
多線程套接字分發(fā)NIO模型是本文網(wǎng)絡(luò)服務(wù)器架構(gòu)中的通信層與事件接口層模型,也是數(shù)據(jù)處理層的基礎(chǔ),向數(shù)據(jù)層提供了事件回調(diào)接口以及TCP數(shù)據(jù)發(fā)送接口。
(一)模型結(jié)構(gòu)
如圖1所示,NIO模型基本可分為以下模塊:
1.通訊層
客戶端代理(TcpClient/TcpClientPool):Tcp客戶端在服務(wù)器端的鏡像,包含了該客戶端鏈路的所有信息,并提供了數(shù)據(jù)發(fā)送的方法??蛻舳舜碇饕ㄌ捉幼滞ǖ琅c輸入緩沖區(qū),緩沖區(qū)大小是應(yīng)用需求而定。
連接接收器(TcpAcceptor):負(fù)責(zé)啟動服務(wù)器的端口監(jiān)聽,并且對生成的監(jiān)聽套接字進(jìn)行select,接收新連接。
鏈路處理器(TcpProcessor/TcpProessorPool):負(fù)責(zé)處理已分配的鏈路事件,驅(qū)動事件接口進(jìn)行業(yè)務(wù)運算。服務(wù)器將根據(jù)鏈路處理器數(shù)量均勻分配客戶端代理,通過實現(xiàn)定義的鏈路處理器池(TcpProessorPool)實現(xiàn)線程池的功能。由于該模型下的高并發(fā)服務(wù)器所服務(wù)的客戶端通訊流量相對比較均勻,因此每一個鏈路處理器將會對該處理器內(nèi)部的socket套接字通道進(jìn)行select,處理器之間并不交換客戶端代理。
2.事件層
事件通知器(EventNotifier):向上層應(yīng)用提供了事件注冊方法,并向底層通訊提供事件驅(qū)動的方法,即register/notify模式。事件通知器將保存進(jìn)行了事件注冊的業(yè)務(wù)對象,并在事件觸發(fā)時以輪詢的方式對事件注冊者的運算進(jìn)行驅(qū)動。
事件適配器接口(EventAdapter):定義了通訊事件觸發(fā)接口,包括OnAccepted(連接建立)、OnRead(數(shù)據(jù)到達(dá))、OnClose(連接關(guān)閉)。
(二)數(shù)據(jù)處理流程
數(shù)據(jù)的處理流程如圖2所示,客戶端A、B、C向服務(wù)器發(fā)起連接,詳細(xì)步驟如下:
如圖2所示NIO模型數(shù)據(jù)處理流程分為以下幾個步驟:
1.客戶端向服務(wù)器發(fā)起連接請求:TcpAcceptor通過select阻塞等待連接到來,當(dāng)selectedKeys為OP_ACCEPT時進(jìn)入建立連接的處理流程。
2.在該模型中對于所有新建立的連接都必須給其分配一個客戶端代理以做到端到端的對應(yīng)。因為連接的關(guān)閉與建立是一個相對比較頻繁的操作,因此TcpAcceptor通過向TcpClientPool請求TcpClient以增加對象的再利用率。
3.在獲得了TcpClient后,模塊需要將TcpClient分配給空閑的TcpPr
ocessor,此處采用平均分配的方式,向TcpProcessorPool申請,選擇其管理TcpClient數(shù)最少的TcpProcessor。
4.在空閑TcpProcessor注冊TcpClient并指定需要監(jiān)視事件。
5.TcpProcessor對已注冊的TcpClient進(jìn)行處理,在數(shù)據(jù)到達(dá)時通過EventNotifer驅(qū)動事件的業(yè)務(wù)處理。
(三)設(shè)計原理對比分析
該NIO模型相對于其他基于NIO技術(shù)的服務(wù)器模型主要優(yōu)勢在三個方面:
1.在NIO的反射模型[3]中,通過Dispatch的中心事件分發(fā)方式,使數(shù)據(jù)處理必須包含對SocketChannel的處理,這樣的層次將降低擴(kuò)展性,因為對于一個便于進(jìn)行二次開發(fā)通訊架構(gòu)應(yīng)該是讓開發(fā)人員無需關(guān)心數(shù)據(jù)是怎么來的。本文中的NIO模型將數(shù)據(jù)的接收和發(fā)送通過事件封裝起來,使數(shù)據(jù)處理代碼與數(shù)據(jù)獲取/發(fā)送代碼分離,從而提高了系統(tǒng)的擴(kuò)展性。
2.基于事件回調(diào)思想下的NIO多線程[5]中將SocketChannel放置在接收線程中select,這樣的作法使得SocketChannel的select與read在不同線程操作時發(fā)生沖突,而導(dǎo)致讀取數(shù)據(jù)的失敗。因此,本文采用均分的機(jī)制將客戶端的SocketChannel的select與read放在同一處理線程中,避免了沖突的發(fā)生。
3.文獻(xiàn)[5]中數(shù)據(jù)的發(fā)送采用事件接口onWrite實現(xiàn),而本文的NIO模型則直接采用又TcpClient提供Send方法的方式,這使得程序設(shè)計便于理解。因為數(shù)據(jù)發(fā)送動作是由上層發(fā)起的,因此使用事件回調(diào)的方式將使操作數(shù)增多,層次將更為復(fù)雜。
四、數(shù)據(jù)處理層架構(gòu)
在有了高效且易于擴(kuò)展的NIO通訊層框架后,服務(wù)器同時需要基于NIO模型之上,便于擴(kuò)展的數(shù)據(jù)處理層的架構(gòu)。在企業(yè)應(yīng)用中存在各式各樣的網(wǎng)關(guān)服務(wù)器程序,例如游戲服務(wù)器,Web服務(wù)器,終端服務(wù)器等,它們都面向連接的數(shù)據(jù)處理服務(wù)程序,對于一個企業(yè)來說程序的可擴(kuò)展性和維護(hù)性是非常重要的,若它們的數(shù)據(jù)處理層架構(gòu)均采用統(tǒng)一模式,這將大大增加服務(wù)器代碼的可閱讀性,維護(hù)性以及擴(kuò)展性。
基于NIO的面向服務(wù)對象的擴(kuò)展業(yè)務(wù)模型的基本概念是將業(yè)務(wù)對象的數(shù)據(jù)處理獨立化,即每一個業(yè)務(wù)處理單元的數(shù)據(jù)處理運算相互獨立,在數(shù)據(jù)處理過程中具有上下文信息。業(yè)務(wù)處理單元采用掛載的方式,一個業(yè)務(wù)處理對象下可以掛載多業(yè)務(wù)處理單元。業(yè)務(wù)處理對象通過對消息類型的判斷將接口的消息分發(fā)給不同的業(yè)務(wù)處理單元進(jìn)行處理。與通訊層不相同的是,業(yè)務(wù)擴(kuò)展模型主要提供標(biāo)準(zhǔn)的基礎(chǔ)類或是接口以供擴(kuò)展,本身并不帶有復(fù)雜的處理邏輯。下面從核心業(yè)務(wù)模塊接口和模塊結(jié)構(gòu)兩方面詳細(xì)描述。
(一)核心業(yè)務(wù)模塊接口定義
命令上下文(CmdContext):在整個單個業(yè)務(wù)處理過程中記錄具體業(yè)務(wù)的歷史信息與當(dāng)前狀態(tài)。通過了加入上下文機(jī)制可以使同一業(yè)務(wù)中的不同操作在不同的時間區(qū)間完成,實現(xiàn)了業(yè)務(wù)的異步化。
命令處理單元(CmdHandler/CmdHandlerGather):所有業(yè)務(wù)處理單元都繼承命令處理單元,CmdHandler包含了標(biāo)準(zhǔn)的上下行數(shù)據(jù)接口,讓業(yè)務(wù)處理單元以標(biāo)準(zhǔn)的方式掛載在業(yè)務(wù)對象上。其中,向上接口表現(xiàn)為指令的處理,而向下接口則是網(wǎng)絡(luò)數(shù)據(jù)的處理。CmdHandler的定時器處理接口(disposeTimeOut)接口還完成了統(tǒng)一的定時器處理,通過該接口實現(xiàn)所有的服務(wù)器單元共享定時器時間片與定時器處理線程池。CmdHandlerGather的作用是將服務(wù)對象將不同類型的指令或消息路由至指定的CmdHandler。
命令發(fā)起者接口(CmdSponsor):主要完成了對指令的路由工作。由于模型采用了Request/Response請求響應(yīng)模式,因此該模式下的業(yè)務(wù)處理必然會以響應(yīng)的方式向通知上層模塊。通過CmdSponsor接口去描述指令發(fā)起者使得業(yè)務(wù)處理可以不再局限于模塊對模塊層面,對于已經(jīng)編寫好的業(yè)務(wù)單元可以通過以其他的業(yè)務(wù)單元為發(fā)起者完成整個業(yè)務(wù)鏈,從而大大增強(qiáng)了代碼的復(fù)用性。
(二)核心業(yè)務(wù)模塊整合
在整合了核心業(yè)務(wù)模塊后,服務(wù)器模型大致可分為:
1.接口模塊:向上層應(yīng)用平臺提供標(biāo)準(zhǔn)的指令接口,并提供接口消息的發(fā)送與接收方法。
2.核心服務(wù)管理模塊:業(yè)務(wù)數(shù)據(jù)的處理核心。通過繼承統(tǒng)一的接口標(biāo)準(zhǔn),完成不同業(yè)務(wù)運算,且服務(wù)對象相互獨立。
3.事件接口:包含了事件通知接口與事件驅(qū)動接口。
4.通訊服務(wù)模塊:基于TCP/IP協(xié)議的通訊平臺,向上提供了數(shù)據(jù)發(fā)送接口以及通過事件驅(qū)動處理單元。
從圖3中可以看出,事件接口與通訊服務(wù)模塊構(gòu)成了整個基于事件驅(qū)動的NIO實現(xiàn)模型,通過線程池驅(qū)動核心服務(wù)管理模塊中的處理單元。定時器線程也是處理單元的運行載體,因此在不考慮具體接口形式時,處理單元將會出現(xiàn)兩個驅(qū)動者。為了保證每一個服務(wù)對象的上下文保持一致,服務(wù)對象的資源方式是需要進(jìn)行同步處理的。
五、應(yīng)用實例
GPS車輛監(jiān)控是在依托于移動網(wǎng)絡(luò)下通過GPS車載終端與服務(wù)端建立通訊連接,進(jìn)而實現(xiàn)車輛的GPS監(jiān)控。對于一些物流型行業(yè),如郵政,煙草配送等,均是具備了數(shù)以萬計的車輛資源,這給GPS系統(tǒng)中的網(wǎng)絡(luò)通訊服務(wù)器的功能和性能又提出了更高的要求。本文介紹的模型已經(jīng)成功應(yīng)用于GPS監(jiān)控系統(tǒng)的業(yè)務(wù)領(lǐng)域,在NIO技術(shù)高性能的基礎(chǔ)上通過以GPS車載終端為服務(wù)對象,向GPS車載提供指令解析以及其他的業(yè)務(wù)服務(wù)功能。
性能方面,基于該模型所開發(fā)的網(wǎng)絡(luò)通信服務(wù)平臺通過了2萬臺GPS終端并發(fā)的壓力測試。GPS終端作為GPS數(shù)據(jù)的通訊器,其數(shù)據(jù)是以相當(dāng)穩(wěn)定的速度向平臺發(fā)送,不會因為外界因素產(chǎn)生大的波動,連接處理器的均勻分配管理模式與GPS終端通信流量穩(wěn)定的性質(zhì)極其吻合。
業(yè)務(wù)擴(kuò)展性方面,在實際GPS產(chǎn)品的通訊協(xié)議解析業(yè)務(wù)的開發(fā)過程中,該模型所提供的接口標(biāo)準(zhǔn)使開發(fā)人員無需關(guān)心平臺除數(shù)據(jù)處理邏輯以外的其他部分。包括通訊服務(wù)模塊,核心服務(wù)處理模塊在內(nèi)的架構(gòu)模塊都已經(jīng)達(dá)到了完全的通用,對于不同的GPS產(chǎn)品(如珠海天琴、上海飛田、深圳龍翰、蘇州宏原等),GPS業(yè)界并沒有一個統(tǒng)一的標(biāo)準(zhǔn)協(xié)議,統(tǒng)一的數(shù)據(jù)處理層框架使程序編寫人員只需要編寫實現(xiàn)業(yè)務(wù)處理單元中的諸如上行、下行以及定時器等標(biāo)準(zhǔn)接口的具體業(yè)務(wù)。
六、結(jié)束與展望
本文提出了基于NIO技術(shù)的多線程套接字分發(fā)服務(wù)器模型,并在此基礎(chǔ)上構(gòu)建了一套具有高擴(kuò)展性的數(shù)據(jù)處理層架構(gòu),從而提供了一個高并發(fā)網(wǎng)絡(luò)應(yīng)用服務(wù)器開發(fā)模型的解決方案。通過實際應(yīng)用的檢驗該模型在性能以及擴(kuò)展性方面都有著良好的表現(xiàn),但該模型在復(fù)雜的網(wǎng)絡(luò)環(huán)境下仍存在一定問題。均勻的連接調(diào)度機(jī)制并不能很好的適應(yīng)多變的應(yīng)用環(huán)境,因此根據(jù)實際應(yīng)用環(huán)境的其它性能指標(biāo)對連接調(diào)度機(jī)制進(jìn)行自適應(yīng)調(diào)整是該模型的下一步的研究方向。
基金項目:國家自然科學(xué)基金(60673164)
參考文獻(xiàn):
[1]劉仕筠、盛志偉、黃健,Linux環(huán)境并發(fā)服務(wù)器設(shè)計技術(shù)研究[J].成都信息工程學(xué)院學(xué)報,2006,21(5):630-634.
[2]王潔,JAVA NIO在Socket通訊中的應(yīng)用[J].成都信息工程學(xué)院學(xué)報,2003,18(3):258-261.
[3]姜力,基于Java NIO反應(yīng)器模式設(shè)計與實現(xiàn)[J].大慶師范學(xué)院報,2008,28(2):27-30.
[4]黃林榕,基于事件的NIO多線程服務(wù)器[DB/OL].http://www.ibm.com/
developer works/cn/java/l-niosvr/.2004.4.1.
[5]Sun Microsystems.Java 2 Platform Standard Edition5.0的API規(guī)范[Z].2004.
作者簡介:
王偉平(1969-),女,副教授,主要從事計算機(jī)網(wǎng)絡(luò)研究。