ICE中介軟體研究筆記
1
2
2.1
2.2
2.2.1
2.2.2
2.2.3
2.3
2.3.1
2.3.2
2.4
2.5
2.6
2.6.1
2.6.2
2.6.3
2.7
2.8
3
1 <wbr><wbr><wbr><wbr><wbr><wbr> ICE中介軟體簡介
Ice 是 Internet Communications Engine 的簡稱,是一種物件導向的中介軟體平臺,支援物件導向的RPC程式設計,其最初的目的是為了提供類似CORBA技術的強大功能,又能消除CORBA技術的複雜性。該平臺為構建物件導向的客戶-伺服器應用提供了工具、API 和庫支援。
ICE平臺還提供一序列的程式設計庫,包括執行緒模型庫、定時器、訊號處理器,這些程式設計庫的API全部支援執行緒安全。
ICE目前的最新版本為ICE3.4.1,是2010年6月份釋出的,ICE3.1.1(2006年10月份釋出)及以前的版本支援Windows、LINUX、AIX、HP-UX、Solaris作業系統,但是ICE3.2.0(包含)以後的版本官方不再保證對AIX的完全支援,而3.3.1(包含)以後版本連HP-UX都不保證完全支援,雖然原始碼中仍然提供了這兩個作業系統下的原始碼編譯檔案Make.rules.AIX和 Make.rules.HP-UX,根據官方的論壇說明是因為他們基本上沒有這兩個系統的商業客戶,所以不再對這兩個平臺進行程式碼測試,如果有需要的需要和他們聯絡。
2 <wbr><wbr><wbr><wbr><wbr><wbr> 平臺核心功能
2.1 <wbr><wbr><wbr><wbr> 介面描述語言(Slice)
Slice (Specification Language for Ice)是一種用於使物件介面與其實現相分離的基礎性抽象機制。Slice 在客戶與伺服器之間建立合約,描述應用所使用的各種型別及物件介面。這種描述與實現語言無關,所以編寫客戶所用的語言是否與編寫伺服器所用的語言相同,這沒有什麼關係。
Slice 定義由編譯器編譯到特定的實現語言。編譯器把與語言無關的定義翻譯成針對特定語言的型別定義和API。開發者使用這些型別和API 來提供應用功能,並與Ice 互動。目前ICE支援Slice到C++、JAVA、C#、Python、Ruby、PHP的語言對映。
Slice示例:
module Family //對應C++的名字空間
{
interface Child;
sequence<Child*> Children; // OK 可以利用C++的Vector
interface Parent //對應C++的類
{
Children getChildren(); // OK
};
interface Child
{
Parent* getMother();
Parent* getFather();
};
};
利用Slice 定義介面/類方法時和其他程式語言很相似,需要一個返回值和若干個引數,但是需要注意的是Slice不支援引用方式的引數傳遞,引數要麼為輸入引數,要麼為輸出引數,不同時為in和out.作為out引數的時候,不管客戶端對out引數的初始賦值是什麼,在服務端都取不到該,但是服務端可以對該引數進行賦值,再傳遞給客戶端。例如:
interface Hello
{
};
2.2 <wbr><wbr><wbr><wbr> ICE執行時
2.2.1 <wbr> 通訊器
Ice run time 的主進入點由本地介面Ice::Communicator 表示,通常一個應用伺服器只使用一個通訊器,一個通訊器例項管理著執行時資源,主要的執行時資源包括:
²
²
²
²
²
²
2.2.2 <wbr> 物件介面卡
一個通訊器含有一個或更多物件介面卡。物件介面卡處在Ice run time和伺服器之間的界線上,負有這樣一些責任:
²
²
²
²
2.2.3 <wbr> 位置透明性
Ice run time 的一個有用的特性是位置透明性:客戶無需知道Ice 物件的實現的位置;對某個物件的呼叫會被自動引導到正確的目標,不管這個物件的實現是在本地地址空間中,在同一臺機器上的另一個地址空間中,還是在一臺遠地機器上的另一個地址空間中。位置透明性十分重要,因為有了它,我們能夠改變物件實現的位置,而不會破壞客戶程式,同時,通過使用IceGrid,像域名和埠號這樣的資訊可以放在應用的外部,不用出現在串化代理中。
2.3 <wbr><wbr><wbr><wbr> 非同步程式設計模型
ICE平臺支援客戶端非同步呼叫(AMI)和服務端非同步分派程式設計(AMD)。
2.3.1 <wbr> 非同步方法呼叫
非同步方法呼叫(AMI) 這個術語描述的是客戶端的非同步程式設計模型支援。如果你使用AMI 發出遠地呼叫,在Ice run time 等待答覆的同時,發出呼叫的執行緒不會阻塞。相反,發出呼叫的執行緒可以繼續進行各種活動,當答覆最終到達時, Ice run time 會通知應用。通知是通過回撥發給應用提供的程式語言物件的。
要使用非同步方法呼叫,只需要給對應的類或者方法前面加上後設資料[“ami”],示例如下:
interface Hello
{
};
通過Slice編譯器生成標頭檔案時,會生成對應的方法同步呼叫方法和非同步呼叫方法,使用者在客戶端可以自行選擇使用同步呼叫還是非同步呼叫,非常方便。編譯後對於每一個非同步方法都會生成相應的非同步回撥類和非同步呼叫代理方法,類的命名方式AMI_類名_方法名,上述的slice經編譯後生成的類為 AMI_Hello_sayHello,同時這個類提供了兩個方法:
void ice_response(<params>);
表明操作已成功完成。各個引數代表的是操作的返回值及out 引數。如果操作的有一個非void 返回型別, ice_response 方法的第一個引數就是操作的返回值。操作的所有out 引數都按照宣告時的次序,跟在返回值的後面。
void ice_exception(const Ice::Exception &);
表明丟擲了本地或使用者異常。
客戶端只需要從AMI_Hello_sayHello 類繼續並實現上述兩個方法就可以了。示例程式碼如下:
class AMI_Hello_sayHelloI : public AMI_Hello_sayHello
{
};
生成的非同步呼叫代理方法命名為方法名_async,上述示例生成的方法為 sayHello_async.然後客戶端的程式非同步呼叫如下:
hello->sayHello_async(AMI_Hello_sayHelloPtr,<params>);
然後只需在ice_response 方法處理返回結果。
也可以呼叫同步方法:
hello->sayHello(<params>);
2.3.2 <wbr> 非同步方法分派
非同步方法分派(AMD) 是AMI 的伺服器端等價物,在使用AMD 時,伺服器可以接收一個請求,然後掛起其處理,以儘快釋放分派執行緒。當處理恢復、結果已得出時,伺服器要使用Ice runtime 提供的回撥物件,顯式地傳送響應。
用實際的術語說, AMD 操作通常會把請求資料(也就是,回撥物件和操作引數)放入佇列 ,供應用的某個執行緒(或執行緒池)隨後處理用。這樣,伺服器就使分派執行緒的使用率降到了最低限度,能夠高效地支援大量併發客戶。
要使用非同步方法呼叫,只需要給對應的類或者方法前面加上後設資料[“amd”],示例如下:
interface Hello
{
};
和非同步方法呼叫不同的是,非同步分派是服務端的,在服務端會生成相應的非同步分派類和非同步分派方法。服務端的分派器在接收到客戶請求時把請求分派給sayHello_async(const Demo::AMD_Hello_sayHelloPtr&, int, const Ice::Current&).然後使用者可以在該方法內把任務引數資訊放入佇列,在佇列中迴圈檢查任務並處理,處理完成後呼叫 AMD_Hello_sayHelloPtr 類的 ice_response 方法返回給客戶端。
2.4 <wbr><wbr><wbr><wbr> 訂閱/釋出程式設計模型
IceStorm是一個高效的用於ICE應用的釋出/訂閱服務,IceStorm有幾個比較重要的概念:
²
²
²
²
IceStorm支援兩個主要的QOS引數reliability 和 retryCount,reliability的取值分別為ordered 和空值,取ordered時,釋出者釋出的訊息會保證按順序遞送給訂閱者。
從IceStorm提供的功能來看,對於不需要進行訊息持久儲存轉發的應用來說很適合,但是由於在訂閱者出錯後立即解除訂閱關係,不是由訂閱者主動解除,這個在應用中需要特別注意是否符合實際應用。
IceStorm被實現為IceBox服務,所以在部署IceStorm應用時需要啟動IceBox服務。
2.5 <wbr><wbr><wbr><wbr> 動態服務管理(IceBox)
IceBox 用於動態載入使用者服務並對他們進行集中管理,可以通過iceboxadmin管理工具對IceBox中的服務進行遠端管理,通過IceBox使用者服務可以被開發成可以動態載入的動態庫元件.
使用IceBox的服務元件需要繼承IceBox::Service類,並實現start()、stop()方法,並在實現類中提供服務進入點函式,一般為create()函式,在這函式中建立服務實現類的物件並返回。例如:
extern "C"
{
ICE_DECLSPEC_EXPORT IceBox::Service*
create(Ice::CommunicatorPtr communicator)
{
}
}
iceboxadmin [options] [command...]
commands:
start SERVICE Start a service.
stop SERVICE Stop a service.
shutdown Shutdown the server.
2.6 <wbr><wbr><wbr><wbr> ICE網格計算
IceGrid用於支援分散式網路服務應用,一個IceGrid域由一個登錄檔(Registry)和任何數目的節點(Node)構成。登錄檔(Registry)和節點(Node)一起合作管理一些資訊以及包含一些應用(Application)的服務程式。每項應用(Application)被指定在特定節點上的服務。這個登錄檔(Registry)持久記錄了這些資訊,而節點(Node)負責啟動和監測其指定的伺服器程式。對於一個典型的配置,一個節點(Node)執行在一臺計算機(稱之為Ice伺服器主機)。登錄檔(Registry)並不消耗很多處理器時間,所以它常常是和一個節點(Node)執行在同一臺計算機上的,登錄檔(Registry)還可以和一個節點(Node)可以執行在同一程式中.如果需要容錯,登錄檔(Registry)還可以用主從式的設計支援複製(Replication)。
登錄檔(Registry)的主要責任,是解決作為Ice定位服務的間接代理問題,當客戶端第一次嘗試使用一種間接代理,客戶端Ice run time首先連線登錄檔(registry),登錄檔將間接代理的符號資訊轉化為直接代理的endpoint,然後客戶端和直接代理建立一個連線。通過介面卡複製,同名介面卡可以分佈在多個節點上,間接代理可以對映到多個節點上的直接代理,在執行時由登錄檔服務根據負載均衡自動選擇一個直接代理給客戶端。
使用間接代理時,客戶端可以用以下方式直接獲取服務物件代理:
MyProxy=theObject@theAdapter
更簡單一點的話可以用以下方式
MyProxy=theObject
2.6.1 <wbr> 分散式部署
在部署IceGrid分散式服務時,需要啟動登錄檔服務(icegridregistry),並配置登錄檔服務地址埠、通訊協議和註冊資訊儲存的目錄地址(ICE的註冊資訊儲存為BerkeleyDB的資料庫檔案):
IceGrid.Registry.Client.Endpoints=tcp -p 4061
IceGrid.Registry.Data=/opt/ripper/registry
在伺服器節點中和客戶端都需要配置登錄檔服務的地址埠和通訊協議:
Ice.Default.Locator=IceGrid/Locator:tcp -h 172.0.0.1 -p 4061
然後分別啟動登錄檔服務(icegridregistry)和節點服務(icegridnode).
ICE提供了部署工具icegridadmin, 這個icegridadmin工具也需要定義Ice.Default.Locator屬性.
接下需要編寫應用部署檔案,應用部署檔案以XML方式儲存。以下為支援介面卡複製的應用配置檔案,使用了服務模板:
<icegrid>
<application name="Ripper">
<replica-group id="EncoderAdapters"> //定義介面卡複製組
<object identity="EncoderFactory"
type="::Ripper::MP3EncoderFactory"/>
</replica-group>
<server-template id="EncoderServerTemplate"> //定義伺服器模板
<parameter name="index"/>
<parameter name="exepath"
default="/opt/ripper/bin/server"/>
<server id="EncoderServer${index}"
exe="${exepath}"
activation="on-demand">
<adapter name="EncoderAdapter"
replica-group="EncoderAdapters"
endpoints="tcp"/>
</server>
</server-template>
<node name="Node1">
<server-instance template="EncoderServerTemplate"
index="1"/>
</node>
<node name="Node2">
<server-instance template="EncoderServerTemplate"
index="2"/>
</node>
</application>
</icegrid>
然後在客戶端可以用以下方式獲取物件代理:
Ice::ObjectPrx obj = communicator->stringToProxy("EncoderFactory");
2.6.2 <wbr> 負載均衡
ICE平臺內嵌負載均衡功能,對於分佈大多個節點上的應用服務提供多種負載均衡方案,只需要通過XML配置檔案即可完成負載均衡配置。配置項包括Type (負載均衡型別)、Sampling interval(負載資訊收集間隙)、Number of replicas(返回給客戶端的介面卡個數)。
負載均衡型別有以下4種方式:
²
²
²
²
配置示例:
<load-balancing type="adaptive"/>
<object identity="EncoderFactory"
type="::Ripper::MP3EncoderFactory"/>
</replica-group>
2.6.3 <wbr> 註冊中心叢集
前兩節中描述的是屬於使用者應用的分佈部署,分散式部署一個很重要的支撐是ICE的註冊中心,所有客戶端都向註冊中心查詢服務代理的真實端點,從而建立通訊連線,在這裡註冊中心又成了一個單點服務,為了避免註冊中心成為應用的瓶頸,提高系統的可靠性,ICE3.3.0以上版本提供了註冊中心叢集功能。
ICE註冊中心叢集通過主從式的註冊中心複製來實現,一個叢集中有一個主註冊中心,若干個副註冊中心,主從的區別通過IceGrid.Registry.ReplicaName屬性配置來實現,主註冊中心的名稱為 Master,其他的名字可以任意取。啟動時先啟動主註冊中心,再啟動其他註冊中心,通過主註冊中心更新的資訊都將同步給副註冊中心,各副註冊中心之間不通訊。如果主註冊中心失效,需要從其他副註冊中心提撥一個成為主註冊中心,但是從3.3版本的說明文件中來看,如果需要把某個副註冊中心提撥成為主註冊中心需要重新啟動相應程式並修改IceGrid.Registry.ReplicaName 屬性值為Master,或者刪除該屬性,預設情況下該屬性值為Master.
使用叢集方式時,在客戶端配置時把所有的主從註冊中心地址埠全部填到Ice.Default.Locator,例如:
Ice.Default.Locator=IceGrid/Locator:default -p 12000:default -p 12001
在應用節點也把所有的註冊中心地址埠繫結,這樣應用的更新會同時通知所有的註冊中心。
2.7 <wbr><wbr><wbr><wbr> IceSSL應用
ICE平臺可以通過簡單的配置來支援SSL應用,配置過程如下:
²
只需要把IceSSL動態庫放到LD_LIBRARY_PATH包含的路徑下即可。
²
MyAdapter.Endpoints=tcp -p 8000:ssl -p 8001:udp -p 8000 //表示該介面卡在三種協議埠上同時監聽。
ICE還提供了多種配置屬性來滿足實際應用,例如下例所示:
Ice.Plugin.IceSSL=IceSSL:createIceSSL
IceSSL.DefaultDir=/opt/certs
IceSSL.CertFile=pubkey.pem
IceSSL.KeyFile=privkey.pem
IceSSL.CertAuthFile=ca.pem
IceSSL.Password=password
2.8 <wbr><wbr><wbr><wbr> 持久化儲存(IceFreeze)
ICE提供的持久化方案可以支援普通使用者資料(鍵/值對)的持久化儲存和服務物件例項的持久化管理,普通使用者資料的持久化儲存使用比較簡單,服務物件例項的管理相對複雜一點,暫時不關注。
ICE的持久儲存介質為BerkeleyDB,對普通資料的持久化在C++實現中採用Map的方式進行操作,使用者需要用Slice定義需要儲存的資料,並用slice2freeze 生成相應的Map操作類,然後對資料的操作就可以使用Map容器函式來進行。示例如下:
首先生成需要儲存的資料型別:
slice2freeze --dict StringIntMap,string,int StringIntMap
程式碼使用:
Ice::CommunicatorPtr communicator =
Ice::initialize(argc, argv);
// Create a Freeze database connection.
Freeze::ConnectionPtr connection = Freeze::createConnection(communicator, "db"); //連線到資料庫檔案。
// Instantiate the map.
StringIntMap map(connection, "simple");//建立表。
// Clear the map.
map.clear();
Ice::Int i;
StringIntMap::iterator p;
// Populate the map.
for (i = 0; i < 26; i++)
{
std::string key(1, 'a' + i);
map.insert(make_pair(key, i));
}
// Iterate over the map and change the values.
for (p = map.begin(); p != map.end(); ++p)
p.set(p->second + 1);
// Find and erase the last element.
p = map.find("z");
assert(p != map.end());
map.erase(p);
// Clean up.
connection->close();
communicator->destroy();
IceFreeze還允許使用結構體和類物件作為值進行儲存,但是隻有public的成員變數會被儲存,其他成員變數不會被儲存。
對於較高版本的ICE,還允許對值建立索引,如果值為結構體或者類物件,那麼還允許以結構體/物件變數作為索引,通過slice2freeze編譯後會生成對應的索引查詢函式。例如定義瞭如下需要儲存的資料結構:
module Demo
{
struct Struct1
{
};
class Class1
{
};
};
然後執行以下命令生成對映表,同時生成索引,以class1的成員變數s為索引。
Slice2freeze
--dict Demo::IndexedStruct1Class1Map,Demo::Struct1,Demo::Class1
編譯後程式碼中會自動生成findByS(string &),在程式中可以按以下方式直接呼叫:
IndexedStruct1Struct2Map
IndexedStruct1Struct2Map
3 <wbr><wbr><wbr><wbr><wbr><wbr> ICE平臺功能研究小結
ICE平臺提供的功能比較多,除了文件中羅列的部分,還支援程式包分發(IcePath2)、防火牆穿透(Glacier),鑑於目前的專案應用暫時不對這兩部分作介紹。
從ICE官方提供的Demo和自己編寫的測試程式在Iinux(opensuse)執行良好,對於適用於AIX的3.1.1版本在AIX上執行非同步程式設計的測試也很順利,但是目前還未對ICE平臺的應用做效能測試。
從文件的介紹,ICE平臺支援同步/非同步、訂閱/釋出、分散式部署、內部持久化儲存,支援介面描述語言到各種物件導向開發語言的對映,可以滿足ESB系統開發的技術需求,但是也有一定的風險,ICE3.1以後的版本對AIX、HP-UX作業系統不保證完全支援,對3.1以後各個升級版本需要進行編譯並執行測試。
相關文章
- 筆記:中介軟體 middleware筆記
- PHP中介軟體ICE,ICE的安裝配置,ICE常見編譯和執行(異常)錯誤PHP編譯
- Django學習筆記(15)——中介軟體Django筆記
- Express的使用筆記3 中介軟體Express筆記
- redux 原始碼研究:中介軟體Redux原始碼
- 訊息中介軟體-kafka學習筆記一Kafka筆記
- Django筆記二十九之中介軟體介紹Django筆記
- ICE原始碼研究原始碼
- Redis中介軟體與Web中介軟體RedisWeb
- 中介軟體之訊息中介軟體-pulsar
- (二)學習瞭解OrchardCore筆記——開篇:OrchardCore的中介軟體筆記
- 《大型網站系統與Java中介軟體》讀書筆記(上)網站Java筆記
- 【筆記】分散式Oracle資料庫中介軟體的核心作用筆記分散式Oracle資料庫
- Laravel學習筆記六-許可權管理與中介軟體MiddlewareLaravel筆記
- ThinkPHP 中介軟體PHP
- redux中介軟體Redux
- golang 中介軟體Golang
- 中介軟體整理
- django中介軟體Django
- Laravel 中介軟體Laravel
- Django——中介軟體Django
- MySQL中介軟體MySql
- 中介軟體-NginxNginx
- 中介軟體漏洞
- 訊息中介軟體Notify和MetaQ-阿里中介軟體阿里
- 【記錄】簡單的跨域中介軟體跨域
- 使用中介軟體記錄Laravel慢請求Laravel
- Asp-Net-Core開發筆記:使用RateLimit中介軟體實現介面限流筆記MIT
- 什麼是中介軟體?Linux常用中介軟體都有哪些?Linux
- MySQL中介軟體--ProxySQLMySql
- websocket gateway 中介軟體WebGateway
- 理解Redux中介軟體Redux
- golang http 中介軟體GolangHTTP
- Django-中介軟體Django
- 理解Express中介軟體Express
- 聊聊 koa 中介軟體
- django--中介軟體Django
- gin使用中介軟體