轉(zhuǎn)載關(guān)于ICE的一篇好文章!

1、ICE是什么?

ICE是ZEROC的開源通信協(xié)議產(chǎn)品,它的全稱是:The Internet Communications Engine,翻譯為中文是互聯(lián)網(wǎng)通信引擎,是一個面向?qū)ο蟮闹虚g件,使我們能夠以最小的代價構(gòu)建分布式應(yīng)用程序。ICE使我們專注于應(yīng)用邏輯的開發(fā),它來處理所有底層的網(wǎng)絡(luò)接口編程,這樣我們就不用去考慮這樣的細節(jié):打開網(wǎng)絡(luò)連接、網(wǎng)絡(luò)數(shù)據(jù)傳輸?shù)男蛄谢c反序列化、連接失敗的嘗試次數(shù)等。

2、為什么會有ICE?

ICE是分布式應(yīng)用的一種比較好的解決方案,雖然現(xiàn)在也有一些比較流行的分布式應(yīng)用解決方案,如微軟的.NET(以及原來的DCOM)、CORBA及WEB SERVICE等,但是這些面向?qū)ο蟮闹虚g件都存在一些不足:

.NET是微軟產(chǎn)品,只面向WINDOWS系統(tǒng),而實際的情況是在當(dāng)前的網(wǎng)絡(luò)環(huán)境下,不同的計算機會運行不同的系統(tǒng),如LINUX上面就不可能使用.NET;

CORBA雖然在統(tǒng)一標(biāo)準(zhǔn)方面做了很多的工作,但是不同的供應(yīng)商實現(xiàn)之間還是缺乏互操作性,并且目前還沒有一家供應(yīng)商可以針對所有的異種環(huán)境提供所有的實現(xiàn)支持,且CORBA的實現(xiàn)比較復(fù)雜,學(xué)習(xí)及實施的成本都會比較高;

WEB SERVICE最要命的缺點就是他的性能問題,對于要求比較高的行業(yè)是很少會考慮WEB SERVICE的。

ICE的產(chǎn)生就是源于.NET、CORBA及WEB SERVICE這些中間件的不足,它可以支持不同的系統(tǒng),如WINDOWS、LINUX等,也可以支持在多種開發(fā)語言上使用,如C++、C、JAVA、RUBY、PYTHON、VB等,服務(wù)端可以是上面提到的任何一種語言實現(xiàn)的,客戶端也可以根據(jù)自己的實際情況選擇不同的語言實現(xiàn),如服務(wù)端采用C語言實現(xiàn),而客戶端采用JAVA語言實現(xiàn),底層的通訊邏輯通過ICE的封裝實現(xiàn),我們只需要關(guān)注業(yè)務(wù)邏輯。

3、ICE是如何工作的?

Ice 是一種面向?qū)ο蟮闹虚g件平臺,這意味著 Ice為構(gòu)建面向?qū)ο蟮目蛻簦?wù)器應(yīng)用提供了工具、API 和庫支持。要與Ice持有的對象進行通信,客戶端必須持有這個對象的代理(與CORBA的引用是相同的意思),這里的代理指的是這個對象的實例,ICE在運行時會定位到這個對象,然后尋找或激活它,再把In參數(shù)傳給遠程對象,再通過Out參數(shù)獲取返回結(jié)果。

這里提到的代理又分為直接代理和間接代理,直接代理其內(nèi)部保存有某個對象的標(biāo)識,以及它的服務(wù)器的運行地址;間接代理指的是其內(nèi)部保存有某個對象的標(biāo)識,以及對象適配器名(object adapter name),間接代理沒有包含尋址信息,為了正確地定位服務(wù)器,客戶端在運行時會使用代理內(nèi)部的對象適配器名,將其傳給某個定位器服務(wù),比如IcePack服務(wù),然后,定位器會把適配器名當(dāng)作關(guān)鍵字,在含有服務(wù)器地址的表中進行查找,把當(dāng)前的服務(wù)器地址返回給客戶,客戶端 run time現(xiàn)在知道了怎樣聯(lián)系服務(wù)器,就會像平常一樣分派 (dispatch)客戶請求。

ICE可以保證在任何的網(wǎng)絡(luò)環(huán)境或者操作系統(tǒng)下,成功的調(diào)用只有一次,它在運行時會盡力的定位到遠程服務(wù)器,在連接失敗的情況下會做嘗試性重復(fù)性連接,確實連不上的情況會給用戶以提示。

客戶端在調(diào)用服務(wù)端的方法時,可以采取同步或異步的方式實現(xiàn),同步調(diào)用就相當(dāng)于調(diào)用自己本地的方法一樣,其它行為會被阻塞;異步調(diào)用是非常有用的調(diào)用方式,如服務(wù)端需要準(zhǔn)備的數(shù)據(jù)來自于其它異步接口,這個時候客戶端就不需要等待,待服務(wù)端數(shù)據(jù)準(zhǔn)備充份后,以消息的方式通知客戶端,服務(wù)端就可以去干其它的事情了,而客戶端也可以到服務(wù)端獲取數(shù)據(jù)了。

4、ICE調(diào)用模式

ICE采用的網(wǎng)絡(luò)協(xié)議有TCP、UDP以及SSL三 種,不同于WebService,ICE在調(diào)用模式上有好幾種選擇方案,并且每種方案正對不同的網(wǎng)絡(luò)協(xié)議的特性做了相應(yīng)的選擇。

Oneway(單向調(diào)用):客戶端只需將調(diào)用注冊到本地傳輸緩沖區(qū)(Local Transport Buffers)后就立即返回,不會等待調(diào)用結(jié)果的返回,不對調(diào)用結(jié)果負責(zé)。

Twoway(雙向調(diào)用):最通用的模式,同步方法調(diào)用模式,只能用TCP或SSL協(xié)議。

Datagram(數(shù)據(jù)報):類似于Oneway調(diào)用,不同的是 Datagram調(diào)用只能采用UDP協(xié)議而且只能調(diào)用無返回值和無輸出參數(shù)的方法。

BatchOneway(批量單向調(diào)用):先將調(diào)用存 在調(diào)用緩沖區(qū)里面,到達一定限額后自動批量發(fā)送所有請求(也可手動刷除緩沖區(qū))。

BatchDatagram(批量數(shù)據(jù)報):與上類似。

不同的調(diào)用模式其實對應(yīng)著不動的業(yè)務(wù),對于大部分的有返回值的或需要實時響應(yīng)的方法,我們可能都采用Twoway方式調(diào)用,對于一些無需返回值或 者不依賴返回值的業(yè)務(wù),我們可以用Oneway或者BatchOneway方式,例如消息通知;剩下的Datagram和BatchDatagram方式 一般用在無返回值且不做可靠性檢查的業(yè)務(wù)上,例如日志。

5、客戶端與服務(wù)端的結(jié)構(gòu)

這個圖示顯示了使用ICE做為中間件平臺,客戶端及服務(wù)端的應(yīng)用都是由應(yīng)用代碼及ICE的庫代碼混合組成的。

客戶應(yīng)用及服務(wù)器應(yīng)用分別對應(yīng)用的是客戶端與服務(wù)端。

代理是根據(jù)SLICE定義的ice文件實現(xiàn),它提供了一個向下調(diào)用的接口,提供了數(shù)據(jù)的序列化與反序化。

ICE的核心部份,提供了客戶端與服務(wù)端的網(wǎng)絡(luò)連接等核心通信功能,以及其它的網(wǎng)絡(luò)通信功能的實現(xiàn)及可能的問題的處理,讓我們在編寫應(yīng)用代碼的時候不必要去關(guān)注這一塊,而專注于應(yīng)用功能的實現(xiàn)。

6、ICE的簡單示例

要使用ICE,必須先安裝ICE,安裝及配置參考如下:

WINDOWS:http://blog.csdn.net/fenglibing/archive/2011/04/28/6368665.aspx

LINUX(BDB的安裝還有問題,無法使用SLICE2JAVA):http://blog.csdn.net/fenglibing/archive/2011/04/27/6367559.aspx

這個示例是JAVA示例,是從ICE的幫助文檔中摘出來的,是一個輸出Hello World的測試程序,采用的ICE版本是3.1.1。

1)、準(zhǔn)備一個ice文件并命名為:Printer.ice,其內(nèi)容為:

[cpp]view plaincopy

module?Demo?{

interface?Printer?{

voidprintString(string?s);

};

};

2)、轉(zhuǎn)到命令行,在Printer.ice文件保存目錄執(zhí)行命令:

slice2java Printer.ice

會在目錄下面生成一個Demo 文件夾,里面會生成一些JAVA文件,如下圖示:

3)、這些文件的類圖結(jié)構(gòu)如下:

這里對生成的一些文件做些解釋,分兩兩部份,服務(wù)端類文件及客戶端類文件:

? .java

這個源文件聲明在ICE文件中定的接口名稱的Java接口,如這里是Printer。

? _Operations.java

_OperationsNC.java

這是兩個定義操作的接口文件,每個接口文件中定義了一個操作實現(xiàn),定義的操作與Slice接口中定義的操作相一致,只是在_Operations.java中定義的方法多了一個參數(shù)“Ice.Current __current”(注:Current對象的定義,請參見3.1.1版本文檔中的31.6 The Ice::Current Object說明),這個參數(shù)的作用是可以允許我們訪問 “正在執(zhí)行的請求”和 “服務(wù)器中的操作的實現(xiàn)”等信息,也就是我們的請求需求需要其它請求的支持時或者要獲取其它請求的執(zhí)行結(jié)果時,我們可以調(diào)用這個方法,這兩個接口文件都會被接口文件_.java繼承。

?? _Disp.java 這個文件包含的是服務(wù)器端骨架類的定義,所用接口定義都要繼承這個東西,這里的接口指供客戶端調(diào)用的接口。

? PrxHolder.java 代理定義holder 類,是對應(yīng)Out參數(shù)使用的。一般參數(shù)都是值傳遞,這個類的作用是使參數(shù)通過引用傳遞。ICE框架應(yīng)用了很多反射機制,這個類是改變遠程參數(shù)的一個映射。

? _Del.java

? _DelD.java

? _DelM.java

不用關(guān)心上面的這些文件,這些文件包含的是供Java 映射內(nèi)部使用的代碼;它們包含的功能與應(yīng)用程序無關(guān)。

? Prx.java 這個是代理接口。例如PrinterPrx,在客戶的地址空間中, PrinterPrx 的實例是“遠地的服務(wù)器中的Printer接口的實例”的“本地大使”。與服務(wù)器端對象有關(guān)的所有細節(jié),比如其地址、所用協(xié)議、對象標(biāo)識,都封裝在該實例中。

注意, PrinterPrx 繼承自Ice.ObjectPrx。這反映了這樣一個事實:所有的Ice 接口都隱式地繼承自Ice::Object。

說的更明白些,就是這個類的方法調(diào)用都是遠程服務(wù)端的調(diào)用,執(zhí)行printString()方法的具體實現(xiàn)是在遠程服務(wù)端執(zhí)行的。

? PrxHelper.java 這個是接口的代理定義助手類,就是幫你獲得代理類的。經(jīng)常用的就兩個方法checkedCast 和 uncheckedCast 。這兩個方法實現(xiàn)的都是向下轉(zhuǎn)換。

注意, checkedCast 會聯(lián)系服務(wù)器。這是必要的,因為只有服務(wù)器情況中的代理實現(xiàn)確切地知道某個對象的類型。所以, checkedCast 可能會拋出ConnectTimeoutException 或ObjectNotExistException(這也解釋了為何需要助手類:ICE在運行時必須聯(lián)系服務(wù)器,所以我們不能使用Java 的向下轉(zhuǎn)換)。

與此相反, uncheckedCast 不會聯(lián)系服務(wù)器,而是會無條件地返回具有所請求的類型的代理 。但是,如果你要使用uncheckedCast,你必須確定這個代理真的支持你想要轉(zhuǎn)換到的類型;而如果你弄錯了,你很可能會在調(diào)用代理上的操作時,引發(fā)運行時異常。對于這樣的類型失配,最后可能會引發(fā)OperationNotExistException,但也有可能引發(fā)其他異常,比如整編異常。而且,如果對象碰巧有一個同名的操作,但參數(shù)類型不同,則有可能根本不產(chǎn)生異常,你最后就會把調(diào)用發(fā)送給類型錯誤的對象;這個對象可能會做出非常糟糕的事情。

4)、建立一個ECLIPSE工程,將生成的文件拷貝到src目錄下,并在classpath中導(dǎo)入Ice.jar。

5)?、建立三個測試JAVA文件,Server.java、PrinterI.java及Client.java:

PrinterI.java是對服務(wù)端實現(xiàn)骨架類_PrinterDisp的實現(xiàn),返回時將PrinterI.java對象返回給客戶端,這里實現(xiàn)的功能是直接輸出傳入的String參數(shù):

[java]view plaincopy

publicclassPrinterIextendsDemo._PrinterDisp?{

publicvoidprintString(String?s,?Ice.Current?current)?{

System.out.println(s);

}

}

Server.java是服務(wù)端服務(wù)代理,用于接收客戶端的請求操作:

[java]view plaincopy

publicclassServer?{

publicstaticvoidmain(String[]?args)?{

intstatus?=0;

Ice.Communicator?ic?=null;

try{

//初使化連接,args可以傳一些初使化參數(shù),如連接超時時間,初使化客戶連接池的數(shù)量等

ic?=?Ice.Util.initialize(args);

//創(chuàng)建名為SimplePrinterAdapter的適配器,并要求適配器使用缺省的協(xié)議(TCP/IP偵聽端口為10000的請求)

Ice.ObjectAdapter?adapter?=?ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter","default?-p?10000");

//實例化一個PrinterI對象,為Printer接口創(chuàng)建一個服務(wù)對象

Ice.Object?object?=newPrinterI();

//將服務(wù)單元增加到適配器中,并給服務(wù)對象指定名稱為SimplePrinter,該名稱用于唯一確定一個服務(wù)單元

adapter.add(object,?Ice.Util.stringToIdentity("SimplePrinter"));

//激活適配器,這樣做的好處是可以等到所有資源就位后再觸發(fā)

adapter.activate();

//讓服務(wù)在退出之前,一直持續(xù)對請求的監(jiān)聽

ic.waitForShutdown();

}catch(Ice.LocalException?e)?{

e.printStackTrace();

status?=1;

}catch(Exception?e)?{

System.err.println(e.getMessage());

status?=1;

}

if(ic?!=null)?{

//?Clean?up

//

try{

ic.destroy();

}catch(Exception?e)?{

System.err.println(e.getMessage());

status?=1;

}

}

System.exit(status);

}

}

Client.java是客戶端代碼,用于向服務(wù)端發(fā)起請求,并操作返回的代理對象:

[java]view plaincopy

publicclassClient?{

publicstaticvoidmain(String[]?args)?{

intstatus?=0;

Ice.Communicator?ic?=null;

try{

//初使化

ic?=?Ice.Util.initialize(args);

//傳入遠程服務(wù)單元的名稱、網(wǎng)絡(luò)協(xié)議、IP及端口,獲取Printer的遠程代理,這里使用的stringToProxy方式

Ice.ObjectPrx?base?=?ic.stringToProxy("SimplePrinter:default?-p?10000");

//通過checkedCast向下轉(zhuǎn)換,獲取Printer接口的遠程,并同時檢測根據(jù)傳入的名稱獲取的服務(wù)單元是否Printer的代理接口,如果不是則返回null對象

Demo.PrinterPrx?printer?=?Demo.PrinterPrxHelper.checkedCast(base);

if(printer?==null)thrownewError("Invalid?proxy");

//把Hello?World傳給服務(wù)端,讓服務(wù)端打印出來,因為這個方法最終會在服務(wù)端上執(zhí)行

printer.printString("Hello?World!");

}catch(Ice.LocalException?e)?{

e.printStackTrace();

status?=1;

}catch(Exception?e)?{

System.err.println(e.getMessage());

status?=1;

}

if(ic?!=null)?{

//?Clean?up

//

try{

ic.destroy();

}catch(Exception?e)?{

System.err.println(e.getMessage());

status?=1;

}

}

System.exit(status);

}

}

6)、運行客戶端和服務(wù)端

運行服務(wù)端:java Server

運行客戶端:java Client

看看效果吧。

7、ICE的性能和效率

ICE的性能是比較好的,因為他本身的傳輸機制都是基于二進制,網(wǎng)上有人曾經(jīng)做過性能測試,評價比較好,我本人還沒有做性能測試,目前的判斷只是基于網(wǎng)絡(luò)數(shù)據(jù),請先看下面的文章:

高性能計算-ICE 性能測試

ICE與CORBA比較的優(yōu)勢

8、ICE的優(yōu)點

支持同步和異步的消息傳遞;

支持多個接口;

機器無關(guān)性,客戶及服務(wù)器與底層的機器架構(gòu)屏蔽開來。對于應(yīng)用代碼而言,像字節(jié)序和填充這樣的問題都隱藏了起來;

語言無關(guān)性,客戶和服務(wù)器可以分別部署,所用語言也可以不同;

實現(xiàn)無關(guān)性,客戶不知道服務(wù)器是怎樣實現(xiàn)其對象的。這意味著,在客戶部署之后,服務(wù)器的實現(xiàn)可以改變;

操作系統(tǒng)無關(guān)性,Ice API 完全是可移植的,所以同樣的源碼能夠在 Windows和 UNIX

上編譯和運行;

線程支持,Ice run time 完全是線程化的,其 API 是線程安全的,作為應(yīng)用開發(fā)者,(除了在訪問共享數(shù)據(jù)時進行同步)無需為開發(fā)線程化的高性能客戶和服務(wù)器付出額外努力。

傳輸機制無關(guān)性,Ice 目前采用了TCP/IP 和 UDP作為傳輸協(xié)議??蛻艉头?wù)器代碼都不需要了解底層的傳輸機制;

位置和服務(wù)器透明性,Ice run time 會負責(zé)定位對象,并管理底層的傳輸機制,比如打開和關(guān)閉連接;

安全性,通過 SSL強加密,可以使客戶和服務(wù)器完全安全地進行通信,這樣,應(yīng)用可以使用不安全的網(wǎng)絡(luò)安全地進行通信,你可以使用 Glacier穿過防火墻,實現(xiàn)安全的請求轉(zhuǎn)發(fā),并且完全支持回調(diào);

內(nèi)建的持久機制,使用 Freeze,創(chuàng)建持久的對象實現(xiàn)變成了一件很容易的事情,Ice提供了對高性能數(shù)據(jù)庫 Berkeley DB[18] 的內(nèi)建支持;

開放源碼。

后記

這里只是簡單的對ICE進行介紹,還有很多東西沒有提到,如ICE的語法規(guī)則、ICE的版本控制(Facet)、持久化 (Feeze)、服務(wù)裝箱管理 (ICEBox)、文件分發(fā)(ICEPatch2)、發(fā)布/訂閱 服務(wù)(ICEStorm)、網(wǎng)絡(luò)拓撲負載解決方案--終極武器(ICEGrid)、提供使用安全傳輸入?yún)f(xié)議SSL的插件(IceSSL)、輕量級的ICE應(yīng)用防火墻其解決方案(Galcier2),這些留待大家后面去學(xué)習(xí)了。



本文轉(zhuǎn)自:http://blog.csdn.net/fenglibing/article/details/6372444

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容