ICE運行環境備忘二

1、需要理解ICE運行環境對客戶端請求的調用分派語義,即當一個請求到來時,如何查找到對應到servant服務對象進行消息處理
   A、在ASM 中查找該標識。如果ASM 有這樣一個條目,就把請求分派到對應的servant。
   B、如果到來的對象標識的範疇不是空的,就查找針對該範疇註冊的servant定位器。如果有這樣的servant 定位器,就調用這個定位器的locate,
      如果locate 返回一個servant,就把請求分派到該servant,然後調用finished ;而如果locate 調用返回null,就在客戶端引發
      ObjectNotExistException。
   C、如果到來的對象標識的範疇是空的,或者在找不到針對該範疇的servant 定位器,就去查找缺省的servant 定位器(也就是,針對空範疇
      註冊的servant 定位器)。如果有缺省的servant 定位器,就像上一步那樣分派請求。
   D、如果上述操作均找不到對應的servant,則在客戶端ObjectNotExistException。
2、通過如下的方法在一個Objectadapter中操作servant的定位器:
    virtual void addServantLocator(const ServantLocatorPtr&, const std::string&);  // 指定範疇註冊定位器,如果範疇爲空,則是默認定位器
    virtual ServantLocatorPtr removeServantLocator(const std::string&);            // 移除定位器,該定位器上不會再有新請求,老請求繼續
    virtual ServantLocatorPtr findServantLocator(const std::string&) const;        // 指定範疇查找定位器
3、Servant定位器的實現樣例:
class OCCIServantLocator : public Ice::ServantLocator
{
public:
virtual Ice::ObjectPtr locate(const Ice::Current&, Ice::LocalObjectPtr&);   
virtual void finished(const Ice::Current&, const Ice::ObjectPtr&, const Ice::LocalObjectPtr&);
virtual void deactivate(const std::string&);
};
注意:
A、ICE調用定位器的locate和finished方法是在同一個線程中進行的。(AMD方法除外)
B、如果locate返回了一個servant,那麼在servant的操作請求完成時,一定會調用finished方法以方便資源回收
C、可以再locate方法中返回一個cookie對象,那麼在finished方法調用時,該cookie會發送給finished方法
D、只有當communicator或者objectadapter對象關閉時,纔會調用定位器的deactivate方法
E、如果在定位器對象中存在一些臨界資源修改,需要對這些臨界資源進行同步互斥保護
F、可以再locate和finished方法中拋出異常,這些異常會拋送給客戶端
4、爲每個服務操作申明實例化一個服務處理對象時最容易理解的普通做法,但是在一個受限資源系統上是不可接受的。爲了解決系統啓動時就創建多個
   servant實例所帶來的缺陷(可能有些servant壓根就不會使用、啓動過程中實例化可能導致比較慢的啓動),可以通過servant定位器來實現延遲實例化
   和按需實例化。
Ice::ObjectPtr MyServantLocator::locate(const Ice::Current & c, Ice::LocalObjectPtr &)
{
   IceUtil::Mutex::Lock lock(_m);

   // Check if we have instantiated a servant already.
   Ice::ObjectPtr servant = c.adapter.identityToServant(c.id);
   if(!servant) { // We don't have a servant already
      // Instantiate a servant.
      servant = new ServantI(c.id.name);
      // Add the servant to the ASM.
      c.adapter->add(servant, c.id);
   }
   return servant;
}
4、默認服務處理對象。默認服務處理對象存在的理由時,要爲每類請求創建一個對應的servant實例在受限資源系統上是不可接受的。
   那麼使用默認的服務處理對象,讓所有請求都用一個實例化對象來處理時一種不錯的選擇,通過如下的方法設置默認服務處理對象:
   virtual void addDefaultServant(const ObjectPtr&, const std::string&);
   在objectadapter上指定特屬範疇的默認服務處理對象。
   那麼爲了能夠區分每個服務調用請求,一種常用的做法是:在服務處理函數中通過current.id.name來區分
   每個servant需要有一個ice_Ping方法來判斷servant是否還存活,由於默認處理對象合併了多數servant的服務調用,因此需要顯示
   的實現ice_Ping方法來判斷current.id.name是否還存活。
5、採用servant定位器來實現servant的按需實例化是一種不錯的改進,但是這樣還是存在一個問題,就是龐大的servant實例往往在資源受限系統上
   得不到滿足,爲此,ICE提供了一種改進的servant定位器"逐出器(evictor)"
   逐出器是一種特殊的servant定位器,除了實現servant定位器的虛擬接口locate和finished之外,還實現了在內部管理了一個所謂的ASM,
   而不是用Objectadapter上的默認ASM來存儲ASM,同時在內部的ASM上實現了LRU的淘汰算法。
   實現一個逐出器的方法如下:
class MyEvictor : public Ice::EvictorBase
{
public:
virtual Ice::ObjectPtr add(const Ice::Current&, Ice::LocalObjectPtr&);
virtual void evict(const Ice::ObjectPtr&, const Ice::LocalObjectPtr&);
};
注意:
A、EvictorBase的回調方法add、evict和ServantLocator的回調方法locate、finished功能類似
B、注意不要試圖在add方法中做類似locate方法中添加servant到ASM中
C、add和evict方法都支持cookie參數的傳遞,可以傳遞用戶指定的上下文信息
D、在類似如數據庫代理的服務系統中,要爲每條記錄創建一個servant對象不太現實,使用默認對象又不太高效,使用Evictor是一個不錯的選擇
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章