基於CORBA的分佈式程序設計(Advanced CORBA Distributed Programming)(六)

第四章 CORBA的服務類型
4.1 詳解CORBA事件服務實現
CORBA事件服務通過對事件(由對象產生並且傳送給其他對象)封裝而提供了基本的消息傳遞功能,在事件被產生之後,CORBA事件服務是將事件從事件提供者對象傳送給事件消費者對象這樣一種機制。而且事件服務允許對象動態地註冊或註銷他們感興趣的特定事件,事件服務在相互不很瞭解的對象之間建立起一條寬鬆耦合的通信信道。事件耦合程度比遠程過程調用要鬆,但比面向消息的中間件(MOM)要緊。

4.1.1兩種事件數據傳送模型:
•推push模型:

在推模型中,事件的提供者起帶頭作用,發起事件的傳送;

•拉pull模型:

在拉模型中,事件的消費者起帶頭作用,向提供者請求事件數據。

事件信道(event channel)是一個既是事件提供者又是事件消費者的插入對象,它允許多個事件提供者和多個事件消費者異步地通信而不需要相互瞭解。事件信道又是一個標準的CORBA對象,駐留在對象請求中介上,斷開提供者和消費者的通信。

事件信道利用代理(proxy)對象撤消時間的提供者和消費者。提供者和消費者不是直接交互作用,而是從事件信道那裏獲得代理對象,讓代理對象在將來的事件交換中代表自己。提供者獲得一個消費者代理,而消費者獲得一個提供者代理。事件信道通過這些代理對象代理事件的交換。

4.1.2事件信道
•對於推模型:

事件提供者發出一個調用,調用事件信道對象上的push方法,事件信道接着把數據推給消費者對象。消費者可以通過調用事件信道上的方法disconnect_push_consumer來停止接受事件,也可以調用事件信道上的connect_push_consumer方法來註冊感興趣的事件類型。

•對於拉模型:

事件消費者發出一個調用,調用事件信道對象上的pull方法,事件信道接着把數據從提供者那裏拉回來。利用try_pull方法,消費者可以週期性地輪詢事件。通過調用事件信道上的disconnect_pull_ supplier方法,提供者可以停止接受要求提供事件的請求,提供者也可以調用事件信道上的add_pull_supplier方法,註冊其對象標記,提供其服務。

我們可以通過理解CORBA事件序列的上下文來理解CORBA事件服務體系結構。

4.1.3推模型
如圖所示的Push事件腳本顯示了一個推提供者通過事件信道向一個推消費者發送事件的簡要過程。

1. 對於一個推模型的推提供者來講,基本的事件序列如下:

(1)綁定到ORB和事件信道上:

org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(agrs,null);

EventChannel eventChannel = EventChannelHelper.bin(orb);

(2) 從事件信道中獲取一個推消費者代理:

SupplierAdmin admin = eventChannel.for_suppliers(); // 對應Push事件腳本的第一步

ProxyPushConsumer pushConsumer = admin .obtain_push_consumer();  // 對應圖中Push事件腳本的第二步

  (3) 創建一個推提供者:

MySupplier pushSupplier = new MySupplier();

(4)將提供者連接到事件信道:

pushConsumer.connect_push_supplier(pushSupplier);//對應圖中Push事件腳本的第三步

(5) 創建一個CORBA消息:

HelloImplementation msg=new HelloImplementation()

(6)利用CORBA消息創建一個Any事件對象:

Org.omg.CORBA.Any pushMessage=orb.create_any();

PushMessage.insert_Object(msg);

(7) 將消息推給消費者:

pushConsumer.push(pushMessage);

// 對應圖中Push事件腳本的第七步

2. 對於一個推模型的推消費者來講,基本的事件序列如下:

(1)綁定到ORB和事件信道上:

org.omg.CORBA.ORB orb= org.omg.CORBA.ORB.init(agrs, null);

EventChannel eventChannel= EventChannelHelper.bin(orb);

(2)從事件信道中獲取一個推提供者代理:

ConsumerAdmin admin= eventChannel.for_consumers();// 對應圖中Push事件腳本的第四步

ProxyPushSupplier pushSupplier = admin .obtain_push_supplier();

// 對應圖中Push事件腳本的第五步

(3) 創建一個推消費者:

MyConsumer pushConsumer=new MyConsumer ();

(4) 將消費者連接到事件信道:

pushSupplier.connect_push_consumer(pushConsumer); // 對應圖中Push事件腳本的第六步

(5) 在一個 push()實現中被接收:

public void push(Any pushMsg)

{

// 對應圖中Push事件腳本的第七步

org.omg.CORBA.Object object=pushMsg.extract_Object();

Hello msg=HelloHeper.narrow(object);

}

4.1.4拉模型
1. 對於一個拉模型的拉提供者來講,基本的事件序列如下:

(1)綁定到ORB和事件信道上:

org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(agrs, null);

EventChannel eventChannel = EventChannelHelper.bin(orb);

(2) 事件信道中獲取一個拉消費者代理:

SupplierAdmin admin = eventChannel.for_suppliers();

ProxyPullConsumer pullConsumer = admin .obtain_pull_consumer();

(3) 創建一個拉提供者:

MySupplier pullSupplier = new MySupplier();

(4) 將提供者連接到事件信道:

pullConsumer.connect_pull_supplier(pullSupplier);

(5) 爲消費者提供一個pull()接口用於拉消息:

public org.omg.CORBA.Any pull()

{

org.omg.OCRBA.Any pullMsg = org.create_any();

HelloImplementation msg = new HelloImplementation();

pullMsg.insert_Object(msg);

ruturn pullMsg;

}

(6) 爲消費者設計一個try_pull()接口,實現只有當一個消息可用時它纔會拉消息的功能:

public Org.omg.CORBA.Any try_pull(org.omg.CORBA.BooleanHolder isAvail)

{ }

2.對於一個拉模型的拉消費者來講,基本的事件序列如下:

(1) 綁定到ORB和事件信道上:

org.omg.CORBA.ORB orb= org.omg.CORBA.ORB.init(agrs, null);

EventChannel eventChannel= EventChannelHelper.bin(orb);

(2) 從事件信道中獲取一個拉提供者代理:

ConsumerAdmin admin= eventChannel.for_consumers();

ProxyPullSupplier pullSupplier = admin .obtain_pull_supplier();

(3) 創建一個拉消費者:

MyConsumer pullConsumer = new MyConsumer ();

(4) 將消費者連接到事件信道:

pullSupplier.connect_pull_consumer(pullConsumer);

(5) 對拉提供者代理調用try_pull()接口或者pull()接口並且將它轉換爲消息類型:

org.omg.CORBA.BooleanHolder hoder = new org.omg.CORBA.BooleanHolder();

org.omg.CORBA.Any pullMsg = pullSupplier.tyr_pull(holer);

org.omg.CORBA.Object obj = pullMsg.extract_Object();

Hello hello = HelloHelper.narrow(obj);

//轉換爲消息類型


圖4-1 Push事件腳本

總的來說,CORBA事件服務只是在CORBA中引入了一個最低限度的MOM通信,它之所以是最低的,是因爲它不支持像MOM那樣的消息優先級、過濾器、交易保護和接受確認等管理機制。儘管如此,CORBA事件服務爲對象動態地註冊或註銷它們感興趣的特定事件提供了一個框架,利用這個框架,提供者可以把事件推給(push)消費者,消費者可以從提供者那裏拉(pull)事件數據,而且多個提供者和消費者可以在一個事件信道上異步通信。件數據,而且多個提供者和消費者可以在一個事件信道上異步通信。

4.2 Corba互操作的命名服務
Corba的對象命名服務就是給對象實例提供一個名稱,以便用戶通過這些名稱來獲取對象的實例。對象命名服務是ORB上的對象找到其它對象的基本機制。名字是用來識別一個對象的可人工辨認的值,命名服務將這些名字映射到對象標記,名字-對象關聯叫做名字聯編。命名語言環境是一個名字空間,對象名字在這裏是獨一無二的。每個對象都有一個獨一無二的參考標識符。可以有選擇地將一個或多個名字與一個對象標記關聯起來。相對於其命名語言環境始終定義一個名字。利用命名服務可以創建命名分層結構,客戶可以搜尋不同的命名語言環境樹,查找所要的對象。來自不同域的名字語言環境可以一起使用,爲對象創建聯合命名服務。CORBA命名分層結構不需要一個“統一”的根目錄。一般情況下,用戶可以規定對象的命名原則,表示對象所在的主機,功能等一系列的信息,這些信息主要包括如下三個方面的內容。

(1) Corba對象的句柄定義成如URL(統一資源定位)的形式,從而允許ORB(Object Request Broker)來調用基於Corba的服務或者遠程ORB上的對象實例

(2) 任何一個廠商的ORB都可以通過配置客戶端的ORB來初始化根命名服務的上下文對象(NamingContext)。

(3) 對於Corba對象的複合命名。定義一個標準的語法規則。這樣服務器端和客戶端就可以通過相同的格式來進行讀寫消息。

下面將分別討論Corba命名服務的一些特點。

一、Corba對象的統一資源定位(URL):Corbaloc

在Internet上,你可以在瀏覽器中直接輸入地址,即Url,就可以到你指定的網站區,這項技術在Corba中也得到了運用。

通常的做法是把一個Corba的服務器放在一臺有指定域名地址和端口的機器上。Corba的服務器要爲許多的Corba對象服務。一般我們需要在對象實例的URL地址後加上特定的對象健值(Object Key ID)或對象名字,這些對象的名字或健值就指明瞭我們所需要的特定的服務。如下所示:

Corbaloc:yourdomain.com/NameService 

其中Corbaloc是Corba URL的關鍵字,用於對象實例和對象句柄的轉換yourdomain.com是所在機器的域名地址或IP地址,/後面的NameService是對象健值.

1.對象的健值

對象的健值是接口對象倉庫的一部分,主要用於表示客戶端調用的特定對象實例。對象健值由ORB在生成對象句柄的過程中生成,並由特定的生成該對象健值的ORB來使用,因此Corba對於它的形式和內容沒有做任何的標準化工作。

對象健值也不一定是一個單詞,它也可以是一個字符串序列。在主域名或IP地址後面,緊跟/的都是對象健值。如:

Corbaloc:yourdomain.com/dev/sand/box/corba/nameservice

其對象健值爲dev/sand/box/corba/nameservice

2.Corbaloc的完整格式和IIOP(Internet Inter-ORB protocal)

(1) Corbaloc URL的完整格式

Corbaloc URL的完整格式如下:

Corbaloc:IIOP:[email protected]:2809/pub/nameservice

即Corbaloc後面的是協議的類型(IIOP是默認的協議類型,可以省略),另一種協議是RIR(Resolove Initial References).1.2是該協議的版本號。由於每一個協議都定義了特定的消息格式,從而來查詢目標對象,因此具體的地址信息包括了特定的協議類型,該協議的版本號,域名地址和端口號。IONA(Internet Association Naming Authority)註冊的默認端口號是2809,在上例中的地址爲:

IIOP:[email protected]:2809,再後面的是對象健值。

 (2)Cobarloc和RIR協議

除了IIOP協議,還有一個RIR協議,通過RIR,可以用URL來訪問ORB的服務把字符串Corbaloc:[email protected]/nameservice傳給string_to_object後,返回與之相對應的對象句柄,在Corbaloc:rir中調用的對象健值,可以是任何一個在resolve_initial_references中定義的健值。

3.編碼以及Corbaloc的使用

每一個ORB都有一個標準的接口,用來把類似URL的字符串,通過string_to_object轉化爲對象句柄。同時返回給一個session的句柄給客戶端,這個session的句柄和你所需要的NameService,TradeService或任何對象健值實現一一的映射。

再服務器端,可以使用兩種方法實現對客戶端的響應。

(1) 通常一個Corba命名或事務的對象實例會接受客戶端的請求,然後把處理的結果返回給客戶,服務器端的程序只要運行在特定端口的網關機器上,接受用戶的請求即可。

(2) 或者爲了減輕網關的負擔,可以在你的網關上安裝一個小的代理軟件,不所有來自客戶端的請求通過Locate_forward來重定向到一個比較穩定的服務器上來處理,在把處理好的結果返回給客戶,網關起到了一個Proxy的作用。

二、對象URL的命名(CorbaName) 

CorbaName運行在Corbaloc之上,用來解析遠程命名服務。如下所示:

CorbaName::yourdomain.org/pub/catalog#year2000/Menswear/outdoors.obj

在#之前,除了CorbaName這個表識符,其它的就是Corbaloc的URL,#之後的就是對象命名的字符串。

把URL的字符串傳給string_to_object函數,ORB把Corbaloc部分解析爲主機命名服務的命名上下文(NamingContext)的一個實例。例如,客戶端的ORB來解析名字上下文pub/catalog實例上的Menswear/outdoors.obj字符串,這些名字實例駐留在域名爲yourdomain.org的Corba服務器上。

三、配置初始的服務和對象的句柄

在客戶端的程序啓動時要對根命名的上下文做一些配置。例如,把所有用戶的ORB指向同一個根;組織和分配服務器上所有的名字空間,是所有的用戶都可以相互交換對象的信息,而不同的用戶也可以組織和分配他們自己的根名字空間和名字空間。客戶端的程序可以通過list_initial_services來查詢已經初始化好的服務。INS(Interoperable Name Service)對也命名服務器中的初始化對象句柄的設置提供瞭如下的三種方式。

1. 管理設置

把一個在該ORB上的服務,配置成爲一個返回遠程對象的句柄

2. ORBInitRef

啓動ORB時,傳遞給系統如下的參數,來設置服務的對象句柄,如下所示:

-ORBInitRef <object_ID>=<object URL>

其中Object Idk可以是一個已經初始化好的服務,也可以是一個Object ID,即在ORB還沒有寫進去之前來初始化一個新的服務號。

Object URL可以是任何的Corba::ORB::string_to_object所支持的URL,如

-ORBInitRef NameService=IOR::0023021ABCS1

也可以用字符形式的Corba IOR來配置命名服務,如 

-ORBInitRef NotificationService=Corbaloc::Tele/NotificationService

3. ORBDefaultInitRef

用ORBDefaultInitRef可以定義默認的URL形式的對象句柄的位置。如下所示:

-ORBDefaultInitRef corbaloc::yourdomain.com

ORG啓動時會調用resolve_initial_references("NotificationService"),然後生成如下的完整的URL,如下所示:

Corbaloc::yourdomain.com/NotificationService

然後把這個完整的URL傳給string_to_object,獲取服務的session句柄,這樣就可以和服務器端進行通信了。

四、總結

通過對象命名服務,可以簡化ORB客戶端和服務器端的通信,提高通信的質量和效率。對提高Corba在Internet在應用起了很大的作用。


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/helloworlder/archive/2003/07/02/20369.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章