(5)ICE通信器是幹嘛的

作用

在運行期間,ice框架爲了完全隔絕通信層對於客戶業務服務的影響,將通信層用到的所有資源都與客戶業務服務用到的資源完全隔離開來了。爲了完成這個目標,寫代碼進行封裝的時候,我們一般封裝一個資源管理類來對通信層所用的資源進行管理,ice則用communicator來實現這個功能。
另一方面,框架爲了完全獨立,一般都有個全局的入口點,類似於程序的入口main函數。ice框架則用Ice::Communicator 來代表運行期間框架的主進入點。

管理的資源

  1. 客戶端線程池
    客戶端線程池會確保,在客戶端,至少有一個線程可用於接收對未完成請求的答覆。這確保了不會發生死鎖。例如,如果服務器在操作實現中回調客戶,即使客戶正在等待同一服務器答覆它的請求,客戶端接收者線程也能處理來自服務器的請求。客戶端線程池還被用於異步方法調用(AMI),用以避免在回調中發生死鎖。
  2. 服務器端線程池
    這個線程池裏面的線程負責接受到來的連接,並處理來自客戶的請求。
  3. 配置屬性
    Ice run time 的各個方面可以通過屬性進行配置。每個通信器都有自己的配置屬性集。
  4. 對象工廠
    爲了實例化從已知基類派生的類,通信器維護有一組對象工廠,能夠替Ice run time 對類進行實例化。
  5. 一個日誌記錄器對象
    日誌記錄器對象實現了Ice::Logger 接口,並負責確定Ice run time產生的日誌消息的處理方式。
  6. 一個統計對象
    統計對象實現了Ice::Stats 接口,通信器會把通信流量(發送和接收字節數)告知該對象。
  7. 一個缺省路由器
    路由器實現了Ice::Router 接口。Glacier 使用了路由器來實現Ice 的防火牆功能功能。
  8. 一個缺省定位器
    定位器是用於把對象標識解析爲代理的對象。定位器對象被用於構建定位服務,比如IcePack 。
  9. 一個插件管理器
    插件是用於給通信器增加特性的對象。例如, IceSSL被實現成插件。每個通信器都有一個插件管理器,這個管理器實現Ice::PluginManager 接口,通過它,你可以訪問通信器的插件集。
  10. 對象適配器
    對象適配器負責分派到來的請求,並把每個請求傳給正確的servant。使用不同通信器的對象適配器和對象完全是相互獨立的。特別地:

    • 每個通信器都使用自己的線程池。例如,這意味着,如果一個通信器耗盡了用於處理到來請求的線程,只有使用該通信器的對象會受影響。使用其他通信器的對象有自己的線程池,因而不受影響。
    • 跨越不同通信器的並置調用不會被優化,而使用同一通信器的並置調用則能避免產生大部分調用分派開銷。服務器通常只使用一個通信器,但有時多個通信器也會很有用。例如,加載的每個Ice 服務使用了單獨的通信器,以確保不同的服務不會相互干擾。多個通信器器還能用於避免線程飢餓:如果一個
      服務耗盡線程,其他的服務不會受影響。

通信器的接口

通信器的接口是用Slice 定義的。下面是其部分接口:

module Ice 
{
    local interface Communicator 
    {
        string proxyToString(Object* obj);
        Object* stringToProxy(string str);
        ObjectAdapter createObjectAdapter(string name);
        ObjectAdapter createObjectAdapterWithEndpoints(string name,string endpoints);
        void shutdown();
        void waitForShutdown();
        void destroy();
        // ...
    };
    // ...
};

通信器提供了一些操作:

proxyToString
stringToProxy

這兩個操作允許你把代理轉換成串化表示,或進行反向轉換。

createObjectAdapter
createObjectAdapterWithEndpoints

這兩個操作創建新的對象適配器。每個對象適配器都與一個或更多傳輸端點關聯在一起。一個對象適配器通常擁有一個傳輸端點。但是,一個對象適配器也可以提供多個傳輸端點。如果是這樣,這些端點可以通往同一組對象,但代表訪問這些對象的不同手段。這很有用,例如,服務器在防火牆後面,但必須讓內部和外部的客戶都能訪問它;把適配器同時綁定到內部和外部接口,就可以其中任何一個接口訪問在服務器中實現的對象了。
createObjectAdapter 根據配置信息來確定把自己綁定到哪個端點,而createObjectAdapterWithEndpoints 允許你爲新適配器指定傳輸端點。你通常會優先於createObjectAdapterWithEndpoints使用createObjectAdapter。這樣,就能把與傳輸機制相關的信息(比如主機名和端口號)放在 源碼外面,通過改變屬性,你可以對應用進行重配置(於是,在傳輸端點需要改變時,不用重新進行編譯)。

shutdown

這個操作關閉服務器端的Ice run time:

  • 在shutdown 被調用時,仍處在執行過程中的操作調用可以正常完成。shutdown 不會等待這些操作完成;在shutdown 返回時,你所知道的是:不會再有新的請求被分派,但在你調用shutdown 時已經在執行之中的操作可能仍在運行。你可以調用waitForShutdown,等待仍在執行的操作完成。
  • 在服務器調用shutdown 之後到達的操作調用或者會失敗(拋出ConnectFailedException),或者會被透明地重定向到服務器的某個新實例。

waitForShutdown

這個操作掛起發出調用的線程,直到通信器關閉爲止(也就是說,直到在服務器中不再有操作在執行爲止)。這樣,你可以在銷燬通信器之前,等待服務器空閒下來。

destroy

這個操作銷燬通信器及其相關資源,比如線程、通信端點,以及內存資源。一旦你銷燬了通信器(因此也就銷燬了該通信器的runtime),你不能再調用其他任何Ice 操作(除非創建另外的通信器)。
在離開程序的main 函數之前要調用destroy,不這樣做會導致不確定的行爲。
在離開main 之前調用destroy 是必需的,因爲destroy 會在返回之前等待所有運行中的線程終止。如果你沒有調用destroy 就離開main,你就會留下許多仍在運行的線程;許多線程包不允許你這樣做,你最終會使程序崩潰。
如果你沒有調用shutdown 就調用destroy,在這個調用返回之前,它會等待所有執行中的操作調用完成(也就是說, destroy 的實現隱含地調用shutdown,然後調用waitForShutdown)。shutdown (因此,也包括destroy)會解除與通信器相關聯的所有對象適配器的激活狀態。Since destroy blocks until all operation invocations complete, a servant will deadlock if it invokes destroy on its own communicator while executing a dispatched operation.
在客戶端,如果你在操作執行過程中調用shutdown,這些操作會終止,拋出CommunicatorDestroyedException。

發佈了31 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章