ICE系列培訓(xùn)(三)_第1頁
ICE系列培訓(xùn)(三)_第2頁
ICE系列培訓(xùn)(三)_第3頁
ICE系列培訓(xùn)(三)_第4頁
ICE系列培訓(xùn)(三)_第5頁
已閱讀5頁,還剩157頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、ICE系列培訓(xùn)(三)鮑齊權(quán)統(tǒng)一網(wǎng)管平臺專項培訓(xùn)內(nèi)容1. ICE運行時2. 動態(tài)ICE3. 連接管理4. Freeze Map1.1 概述本章主要介紹ICE運行時的一些內(nèi)部細(xì)節(jié):通信器ICE上下文對象適配器連接超時對象標(biāo)識單向、數(shù)據(jù)報、批量調(diào)用Current對象定位服務(wù)Servant自動重試ICE線程模型字符串編碼代理插件開發(fā)1. ICE運行時1.2 通信器通信器Ice:Communicator是Ice運行時的主入口點,其實例與一些運行時資源關(guān)聯(lián)在一起:客戶端線程池對象適配器服務(wù)端線程池配置屬性對象工廠日志記錄器統(tǒng)計對象缺省路由器缺省定位器插件管理器1. ICE運行時1.2 通信器注意:不同通信

2、器的對象適配器以及ICE對象是相互獨立的;不同通信器使用其自己的線程池,互不干擾;通常情況下,一個服務(wù)器中使用一個通信器即可;某些情況下多通信器更有用:例如,IceBox對每個Ice服務(wù)使用不同的通信器這樣保證不同服務(wù)間互不干擾;1. ICE運行時1.2 通信器通信器接口:module Icelocal interface Communicatorstring proxyToString(Object *obj);Object *stringToProxy(string str);通信器提供大量接口來操作它所關(guān)聯(lián)的運行時資源,后面介紹各個資源時再介紹。1. ICE運行時1.3 通信器的初始化在

3、創(chuàng)建通信器時,ICE運行時初始化了一系列通信器特性,這些特性影響通信器的行為;注意:這些特性生命期隨通信器生命期一起,通信器創(chuàng)建后就不能更改了。因此,你必須在創(chuàng)建通信器時設(shè)置好這些特性; 初始化使用Ice:initialize函數(shù):namespace Ice CommunicatorPtr initialize(int&, char*, const InitializationData& = InitializationData(), Int = ICE_INT_VERSION); CommunicatorPtr initialize(StringSeq&, const

4、 InitializationData& = InitializationData(), Int = ICE_INT_VERSION); CommunicatorPtr initialize(const InitializationData& = InitializationData() Int = ICE_INT_VERSION); 1. ICE運行時1.3 通信器的初始化通信器創(chuàng)建時可以定制下列特性: 屬性集合屬性集合 日志接口日志接口 狀態(tài)接口狀態(tài)接口 寬寬/ /窄字符集轉(zhuǎn)換器窄字符集轉(zhuǎn)換器 線程通知線程通知hookhook 分派器分派器 類裝載器(僅類裝載器(僅java

5、java) 1. ICE運行時1.3 通信器的初始化要建立這些特性,你需要填充一個InitializationData結(jié)構(gòu): namespace Ice struct InitializationData PropertiesPtr properties; LoggerPtr logger;StatsPtr stats;StringConverterPtr stringConverter;WstringConverterPtr wstringConverter;ThreadNotificationPtr threadHook; DispatcherPtr dispatcher; ; ; 1.

6、ICE運行時示例:運行時屬性集可從文件中讀取InitializationData initData;initDperties = createProperties();initDperties-load(configFile);1.3 通信器的初始化例如:定制一個類型為MyLogger的日志記錄器 Ice:InitializationData id;id.logger = new MyLoggerI; Ice:CommunicatorPtr ic = Ice:initialize(argc, argv, id);1. ICE運行時例如,我們的總線客戶端的通信器是在下

7、面所示函數(shù)內(nèi)初始化的:void CBusClientForRpcClient:ClientInit(const string &strUnmBusRegistryServerAddress, const string &strClientName)Ice:InitializationData initData;m_poVar-m_poRpcCommunicator = Ice:initialize(initData);1.4 對象適配器對象適配器是位于Ice運行時和實際服務(wù)提供對象(Servant)之間,實現(xiàn)以下職責(zé):(1)將Ice對象(培訓(xùn)一中有介紹什么是Ice對象和Serv

8、ant)映射到Servant,并分派請求給Servant;(2)輔助Ice對象和Servant的生命期操作;(3)提供傳輸端點;注意:每個通信器可擁有一個或多個對象適配器;每個對象適配器可擁有一個或多個Servant;每個對象適配器可擁有多個傳輸端點,這些傳輸端點代表的是通向同一組對象的不同路徑;每個對象適配器可非強制性擁有自己的線程池(通過.ThreadPool.Size設(shè)置)如果設(shè)置了適配器自己的線程池,那么給對象適配器的分配操作將使用自己線程池中的線程,而不會使用通信器中的線程池。1. ICE運行時1.4.1 活動Servant映射表每個對象適配器都維護有一個活動Servant映射表(A

9、SM)。對于收到的客戶端請求,對適配器會根據(jù)對象標(biāo)識到ASM中查找正確的Servant來分派這個請求。注意:如果客戶端請求包含的對象標(biāo)識無法在ASM中找到正確的Servant,則適配器會返回ObjectNotExistException異常給客戶端(適配器沒有使用Servant定位器時)1. ICE運行時1.4 對象適配器1.4.2 ServantsServant是位于服務(wù)端,為客戶端提供實際服務(wù)業(yè)務(wù)的Ice對象實例,它使用具體語言實現(xiàn)Ice接口。注意:同一Servant可注冊給多個對象適配器;Ice:ObjectAdapterPtr adapter = communicator()-crea

10、teObjectAdapter(Hello);/ ServantDemo:HelloPtr hello = new HelloI; adapter-add(hello, communicator()-stringToIdentity(hello);adapter-activate();1. ICE運行時1.4 對象適配器HelloI實現(xiàn)的接口Slice定義:module Demo interface Hello idempotent void sayHello(int delay); void shutdown(); ;接口實現(xiàn):class HelloI : public Demo:Hello

11、;1.4.3 對象適配器的創(chuàng)建及提供的接口對象適配器的創(chuàng)建:使用通信器提供的方法::Ice:ObjectAdapterPtr createObjectAdapter(const :std:string&);:Ice:ObjectAdapterPtr createObjectAdapterWithEndpoints(const :std:string&, const :std:string&);:Ice:ObjectAdapterPtr createObjectAdapterWithRouter(const :std:string&, const :Ice:Rou

12、terPrx&);對象適配器提供了大量本地接口可用來訪問適配器:module Ice local interface ObjectAdapter string getName(); Communicator getCommunicator(); / . ; ; 1. ICE運行時1.4 對象適配器示例: Ice:ObjectAdapterPtr adapter = ic-createObjectAdapterWithEndpoints( SimplePrinterAdapter, default -p 10000);1.4.4 Servant的激活與解除激活Servant激活:告知Ic

13、e運行時某個Servant的存在(加入ASM)。解除激活:將Servant從ASM中移除。對象適配器提供了add函數(shù)來激活和解除Servant:Object *add(Object servant, Identity id);Object *addWithUUID(Object servant);void remove(Identity id);1. ICE運行時1.4 對象適配器1.4.4 Servant的激活與解除激活注意:不允許使用同一標(biāo)識激活多次;不同標(biāo)識可用來激活同一Servant多次,這種情況下同一Servant將表現(xiàn)為多個Ice對象;addWithUUID會自動為Servant生

14、成一個UUID作為對象標(biāo)識。Demo:HelloPtr hello = new HelloI; / Servant adapter-add(hello, communicator()-stringToIdentity(hello);1. ICE運行時1.4 對象適配器1.4.5 對象適配器狀態(tài)對象適配器具有三種狀態(tài):保持狀態(tài)(holding);活動狀態(tài)(active);不活動狀態(tài)(inactive)。1. ICE運行時1.4 對象適配器1.4.5 對象適配器狀態(tài)保持狀態(tài)(holding)處于保持狀態(tài)的適配器,任何到來的請求客戶端都會收到TimeoutException或ConnectTimeo

15、utException異常。注意:出于保持狀態(tài)下面向流協(xié)議的適配器(TCP/IP),服務(wù)端運行時會停止從相應(yīng)的傳輸端點讀數(shù)據(jù),同時也會拒絕客戶端的連接請求。對象適配器提供的操作:void Ice:ObjectAdapter:hold();該操作或?qū)⑦m配器置為hold狀態(tài),但是不會等待已有請求的完成,會立即返回。void Ice:ObjectAdapter:waitForHold();該操作會阻塞調(diào)用線程,知道所有已有請求完成。1. ICE運行時1.4 對象適配器1.4.5 對象適配器狀態(tài)活動狀態(tài)(active)活動狀態(tài)下的適配器可以接收并分派請求到servant注意:新創(chuàng)建的適配器初始化狀態(tài)是

16、Holding狀態(tài);雙向連接的適配器不需要激活(雙向連接參見1.7);并置調(diào)用(collocated invocation)即使適配器沒有激活調(diào)用也會成功,除非你禁用了并置調(diào)用優(yōu)化。對象適配器提供的操作: void Ice:ObjectAdapter:activate();激活對象適配器,例如:Ice:ObjectAdapterPtr adapter = communicator()-createObjectAdapter(Hello); Demo:HelloPtr hello = new HelloI; / Servant adapter-add(hello, communicator()-

17、stringToIdentity(hello); adapter-activate(); / 激活適配器1. ICE運行時1.4 對象適配器1.4.5 對象適配器狀態(tài)不活動狀態(tài)( inactive )不活動狀態(tài)下,適配器在概念上已經(jīng)被銷毀了。一旦適配器處于不活動狀態(tài),那么它將不能再被重新激活對象適配器提供的操作: void Ice:ObjectAdapter:deactivate(); void Ice:ObjectAdapter:waitForDeactivate(); void Ice:ObjectAdapter:isDeactivated(); void Ice:ObjectAdapte

18、r:destroy();1. ICE運行時1.4 對象適配器1.4.6 Endpoints(端點)Endpoints:由:傳輸協(xié)議、主機名、端口組成;格式:protocal h host addr1 p port No.: protocal h host addr2 p port No.一個對象適配器維護有兩組傳輸端點:一組用于對象適配器監(jiān)聽新的連接物理傳輸端點;一組嵌入適配器創(chuàng)建的代理對象中,用于客戶端通信使用(發(fā)布端點)published endpoints; (大多數(shù)情況下,這兩組端點是一樣的,但它們是可以獨立配置的)1. ICE運行時1. ICE運行時1.4 對象適配器1.4.6 En

19、dpoints(端點)物理端點(Physical Endpoints )物理傳輸端點是對象適配器用來接收客戶端請求用的; 可由:name.Endpoints屬性或createObjectAdapterWithEndpoints方法進行設(shè)定;例如:Hello.Endpoints=tcp -p 10000:udp -p 10000:ssl -p 10001注意:(1)如果端點中定義了主機名,那么對象適配器只能監(jiān)聽該網(wǎng)絡(luò)接口上的請求;(2)如果端點中未定義主機名,但是屬性Ice.Default.Host定義了,那么對象適配器將監(jiān)聽Ice.Default.Host定義的主機名的端點;(3)如果上面兩者

20、都未定義,那么對象適配器將監(jiān)聽所有網(wǎng)絡(luò)接口;1. ICE運行時1. ICE運行時1.4 對象適配器1.4.6 Endpoints(端點)注意:(4)如果要強制對象適配器監(jiān)聽所有網(wǎng)絡(luò)接口,則可定義端點中的主機名為或*;(5)如果端點中指定了主機名,但是沒有指定回環(huán)接口,那么回環(huán)接口是不會被監(jiān)聽的,必須加入后才能監(jiān)聽回環(huán)接口:MyAdapter.Endpoints=tcp h p 9999:tcp h p 9999(6)如果端點中沒有指定端口,則對象適配器會使用系統(tǒng)選擇的一個端口進行監(jiān)聽(該端口不固定);1. ICE運行時1. ICE運行時1.4

21、 對象適配器1.4.6 Endpoints(端點)發(fā)布端點(Published Endpoints ) 對象適配器創(chuàng)建代理對象時,需要發(fā)布它的傳輸端點,但是它不能發(fā)布它的物理傳輸端點;例如,一個服務(wù)運行在防火墻后的私有網(wǎng)絡(luò)內(nèi),它的適配器的物理端點使用的是私有網(wǎng)絡(luò)的地址,如果將物理端點發(fā)布在對象適配器創(chuàng)建的代理中,那么公共網(wǎng)絡(luò)中的客戶端是無法使用的。 這種情況下適配器必須在它的代理中發(fā)布能夠指引客戶端通過防火墻的端點。 使用name.PublishedEndpoints配置發(fā)布端點; 如果未配置上述屬性,則適配器會使用物理端點(注意:除非只有回環(huán)接口,否則回環(huán)接口不會被發(fā)布)例如: MyAdap

22、ter.Endpoints=tcp h p 9999 MyAdapter.PublishedEndpoints=tcp h corpfw p 25000 表示連接在主機名為corpfw端口25000的客戶端會被轉(zhuǎn)發(fā)到適配器的物理端點上(私有網(wǎng)絡(luò)上的端點)。1. ICE運行時1. ICE運行時1.4 對象適配器1.4.6 Endpoints(端點)發(fā)布端點還可用于多服務(wù)負(fù)載平衡時: 假設(shè)有兩個狀態(tài)無關(guān)的服務(wù)運行在兩個不同的主機上以實現(xiàn)負(fù)載平衡。一般情況下客戶端使用的代理對象的端點同時包含兩個服務(wù)的端點,這樣Ice運行時可以隨機選擇一個服務(wù)建立連接。 但是,如果客戶端調(diào)用了服務(wù)的

23、某操作后,該操作返回了一個該服務(wù)的代理對象。那么,客戶端使用這個返回代理對象調(diào)用操作時Ice運行時會始終選擇返回該代理的服務(wù)端(因為返回的代理中只有創(chuàng)建它的服務(wù)端端點),無法負(fù)載平衡。 這種情況下要負(fù)載平衡可以配置服務(wù)端適配器的發(fā)布端點,讓發(fā)布端點同時包含兩服務(wù):(假設(shè)兩個服務(wù)一個叫sun1,一個叫sun2) 1. ICE運行時1. ICE運行時1.4 對象適配器對于sun1 MyAdapter.Endpoints=tcp h sun1 p 9999 MyAdapter.PublishedEndpoints=tcp h Sun1 p 9999:tcp h Sun2 p 9999對于sun2 M

24、yAdapter.Endpoints=tcp h sun2 p 9999 MyAdapter.PublishedEndpoints=tcp h Sun1 p 9999:tcp h Sun2 p 99991.4.6 Endpoints(端點)刷新端點 主機的網(wǎng)絡(luò)接口列表可能會動態(tài)改變。例如,筆記本電腦從一個無線網(wǎng)絡(luò)移動到另外的無線網(wǎng)絡(luò)時。 這時對象適配器提供刷新網(wǎng)絡(luò)接口列表的方法: local interface ObjectAdapter void refreshPublishedEndpoints(); / ; 注意:刷新時機由應(yīng)用程序自己決定; 只有那些發(fā)布端點中沒有配置主機地址或配置的是

25、全部地址(*或)的對象適配器,該刷新才有效。1. ICE運行時1. ICE運行時1.4 對象適配器1.4.6 Endpoints(端點)端點的超時屬性 作為防備惡意客戶端的手段,建議在物理端點中指定超時時間。 超時會影響那些Ice運行時通常不希望長時間阻塞的任務(wù):向socket寫回應(yīng)消息或等待SSL磋商完成等。如果沒有設(shè)置超時,那么運行時會無限等待。這樣一些惡意客戶端就能夠大量消耗資源。端點中使用-t參數(shù)設(shè)置超時MyAdapter.Endpoints=tcp p 9999 t 50001. ICE運行時1. ICE運行時1.4 對象適配器1.4.6 Endpoints(端點)路由

26、器如果對象適配器配置了路由器,那么適配器的發(fā)布端點會影響路由器(詳見手冊42章關(guān)于如何使用路由器配置對象適配器)1. ICE運行時1. ICE運行時1.4 對象適配器1.4.7 創(chuàng)建代理 對象適配器接口提供多種方法創(chuàng)建代理對象(不管對象id表示的Servant是否是激活的): Object * ObjectAdapter:createProxy(Identity id);它返回直接代理還是間接代理由對象適配器的配置決定。如果對象適配器是用的適配器id,則返回間接代理;如果對象適配器沒有id,那么該接口使用適配器發(fā)布端點返回一個直接代理; Object * ObjectAdapter:creat

27、eDirectProxy(Identity id); 該接口直接返回一個直接代理,代理端點為適配器的發(fā)布端點;Object * ObjectAdapter:createIndirectProxy(Identity id); 返回一個間接代理。直接代理其內(nèi)部保存有某個對象的標(biāo)識,以及它的服務(wù)器的運行地址;間接代理其內(nèi)部保存有某個對象的標(biāo)識,以及對象適配器名(object adapter name)。1. ICE運行時1. ICE運行時1.4 對象適配器1.4.8 使用多對象適配器 一個典型的服務(wù)實現(xiàn)很少需要使用多個對象適配器。如果你正考慮使用多個對象適配器,則建議你考慮是否用到了下列情況:(1)

28、. 你需要一個細(xì)粒度的對象訪問控制。例如,已可能有一個適配器僅綁定一個安全的端點來限制訪問一些管理對象,其它的適配器綁定到非安全端點上用來訪問其它對象;(2). 針對不同集合的對象,你需要控制線程池中線程數(shù)量。例如:某個特定的適配器上的對象不需要并發(fā)處理,而是設(shè)置多個適配器,每個適配器有各自的線程池,這樣可用于解決死鎖;(3). 你需要針對某一組對象能夠暫時禁用它上面的新請求。這可以通過設(shè)置相應(yīng)的對象適配器的狀態(tài)為Holding來完成;(4). 當(dāng)你在Glacier2中使用一個Ice路由器時能設(shè)置不同請求路徑時可以考慮使用多適配器; 如果你的應(yīng)用中沒有上述情形,則你無須使用多適配器; 1. I

29、CE運行時1. ICE運行時1.4 對象適配器1.5 對象標(biāo)識(Object Identity)每一個Ice對象都有如下定義的一個對象標(biāo)識:module Ice struct Identity string name; string category; ; ; 標(biāo)識可以用字符串標(biāo)示:category/name通信器成員函數(shù):string identityToString(Identity id);Identity stringToIdentity(string id);可用于相互轉(zhuǎn)換1. ICE運行時示例:Demo:HelloPtr hello = new HelloI; / Servant/

30、 下面用“hello”字符串作為對象標(biāo)識adapter-add(hello, communicator()-stringToIdentity(hello);1.6 Ice:Current對象每個傳給服務(wù)端骨架操作的最后一個參數(shù)都是Ice:Current對象;module Ice local dictionary Context; enum OperationMode Normal, Nonmutating, Idempotent ; local struct Current ObjectAdapter adapter; 分派該操作的對象適配器Connection con; 接收該請求的連接信息

31、Identity id; 處理當(dāng)前請求的對象標(biāo)識string facet; (參見33章)string operation; 當(dāng)前調(diào)用的操作名OperationMode mode; 調(diào)用模式Context ctx; 當(dāng)前調(diào)用上下文(參見手冊32.12)int requestId; 請求ID用來關(guān)聯(lián)請求和請求回應(yīng); ; 1. ICE運行時例如: virtual void sayHello(:Ice:Int, const :Ice:Current& = :Ice:Current() = 0;1.7 Servant定位器 Servant定位器是一個注冊到對象適配器的對象,當(dāng)?shù)絹淼恼埱笤贏SM

32、中無法找到正確的Servant時,會調(diào)用該定位器對象,由定位器對象返回一個正確的Servant來處理這個請求。沒有定位器時:(1)每個Ice對象都由一個不同的Servant表示;(2)每個Ice對象對應(yīng)的Servant必須駐留在內(nèi)存中; 如果Servant的數(shù)量很多時,會面臨內(nèi)存壓力問題;使用Servant定位器:允許Servant實例數(shù)量小于Ice對象數(shù)量;運行時由定位器根據(jù)需要實例化Servant。1. ICE運行時1.7 Servant定位器 要實現(xiàn)定位器,你需要繼承自Ice:ServantLocator,并實locate,finished,deactivate方法。 如果到來的請求在A

33、SM中找不到Servant,則Ice運行時會掉調(diào)用locate方法; locate返回一個Servant,Ice運行時會將請求分派給該Servant,請求完成后,Ice運行時會調(diào)finished; 定位器銷毀時deactivate會被調(diào)用。1. ICE運行時1.7 Servant定位器定位器的線程保證:同步操作Ice運行時保證,調(diào)用locate和finished是配對的且在同一線程內(nèi)的;異步分派的操作Ice運行時不保證調(diào)用locate和finished是同一線程;如果在locate和finished中訪問了共享數(shù)據(jù),則必須加以保護。1. ICE運行時1.7 Servant定位器向?qū)ο筮m配器注冊

34、一個定位器:使用對象適配器方法void addServantLocator(ServantLocator locator, string category);進行注冊。注意:必須提供category實參,它決定這個定位器要負(fù)責(zé)的Ice對象標(biāo)識(那些對象標(biāo)識與定位器category匹配的Ice對象才會觸發(fā)該定位器的locate調(diào)用)1. ICE運行時1.8 缺省Servants還可以使用缺省Servants來解決Servants量很大的問題。它根據(jù)請求對象標(biāo)識的不同改變其行為??赏ㄟ^對象適配器方法:void addDefaultServant(Object servant, string cat

35、egory);添加缺省Servant。注意:缺省Servant需要保護共享數(shù)據(jù)。1. ICE運行時1.9 服務(wù)器實現(xiàn)技術(shù)1.9.1 漸進初始化如果使用了Servant定位器,locate方法返回的Servant實例只能用于當(dāng)前請求(Ice運行時不會將該Servant加入ASM)。所以,Servant的初始化是分散到每次請求調(diào)用中的,而不是服務(wù)啟動時(也可以在locate首次實例化了某Servant后將其加入ASM,這樣后面的調(diào)用請求不再需要初始化該Servant了);內(nèi)存需求也有所降低,因為只有那些被訪問到的Servant才會被實例化。1. ICE運行時1.9 服務(wù)端實現(xiàn)技術(shù)1.9.2 缺省S

36、ervants針對不同的請求,缺省Servant能充當(dāng)不同角色。根據(jù)訪問對象標(biāo)識改變其行為。例如:我們目前的服務(wù)端中使用了類似的實現(xiàn)方式(雖然不是使用的缺省Servant,但只使用了一個Servant對象來處理所有請求)bool CBusClientForRpcServer:RegisterRpcService(const string &strAppName, const CRpcObjectPtr &rpcObject)CRpcObjectAdapterPtr poAdapter = m_poVar-m_poMainAdapter;poAdapter-add(rpcObje

37、ct, m_poVar-m_poRpcCommunicat-stringToIdentity(strAppName);poAdapter-activate();return true;1. ICE運行時1.9 服務(wù)端實現(xiàn)技術(shù)1.9.3 混合途徑及緩存(Hybrid Approaches and Caching)即:一些性能要求較高的Servant可直接加入ASM中,其它不經(jīng)常訪問的對象可通過缺省Servant實現(xiàn)。1. ICE運行時1.9 服務(wù)端實現(xiàn)技術(shù)1.9.4 Servant逐出器(Servant Evictors)逐出器是維護有servants 緩存的servant 定位器。 只要有請求

38、到達(也就是說, Ice run time 調(diào)用了locate),逐出器就在它的緩存中檢查,看是否能找到可用于該請求的servant。如果有,它就返回這個已經(jīng)在緩存中實例化的servant ;否則,它實例化一個servant,并把它增加到緩存中。 緩存是一個按照“最近最少使用”(LRU)順序維護的緩存:最近最少使用的servant 處在隊列的尾部,最近使用最多的servant 處在隊列的頭部。如果某個servant 被從緩存中返回,或增加到緩存中,它就會從當(dāng)前的隊列位置移到隊列頭部,也就是說,“最新”的servant 總是在頭部,“最老”的servant 總是在尾部。 隊列的長度可以配置,并決

39、定會有多少servant 存放在緩存中;如果針對某個Ice 對象的請求在內(nèi)存中沒有對應(yīng)的servant,且緩存滿了,逐出器就會在隊尾移除最近最少使用的servant,給要在隊頭實例化的servant騰出空間。 1. ICE運行時1.9 服務(wù)端實現(xiàn)技術(shù)1.9.4 Servant逐出器(Servant Evictors)逐出器的實現(xiàn)和實現(xiàn)定位器一樣,只是該定位器中需要增加一個“最近最少使用”(LRU)隊列來緩存實例化過的Servant。class EvictorBase : public Ice:ServantLocator / ;1. ICE運行時1.10 Ice線程模型Ice天生是一個多線程平

40、臺,不存在單線程的Ice服務(wù)。你必須考慮并發(fā)問題。 例如:請求可能被并發(fā)分派。1. ICE運行時1.10.1 線程池介紹每個通信器創(chuàng)建兩個線程池:1. 客戶端線程池;(響應(yīng)請求回應(yīng)、AMI回調(diào))2. 服務(wù)端線程池;(分派請求、雙向連接回應(yīng))缺省情況下,這兩個線程池被通信器的所有適配器共享。如果需要,你可以為某個對象適配器配置私有的線程池;如果線程池中線程耗盡,則新的請求會被阻塞; 默認(rèn)池中線程數(shù)為1.1. ICE運行時1.10 ice線程模型1.10.2 配置線程池每個線程池有一個唯一的名字;有下列屬性可設(shè)置:Name.SizeName.SizemaxName.SizeWarnName.Sta

41、ckSizeName.SeralizeName.ThreadIdleTime 客戶端和服務(wù)端線程池的名字為: Ice.ThreadPool.Client和Ice.ThreadPool.Server如果要監(jiān)視線程池活動情況,可打開屬性Ice.Trace.ThreadPool屬性。 動態(tài)線程池:由name.Size、name.Sizemax、name.ThreadIdleTime決定 (Ice運行時會按這些參數(shù)配置,動態(tài)決定池中的線程數(shù))1. ICE運行時1. ICE運行時1.10 ice線程模型例如,我們的Ice服務(wù)配置如下:1.10.3 適配器線程池 缺省情況下對象適配器和通信器是共享線程池的

42、。但是,在某些特殊情況下配置對象適配器自己的線程池也是很有用的: 1. 當(dāng)對象適配器的并發(fā)要求和通信器的并發(fā)要求不一致時; 2. 確保對某個適配器的Servants的請求分派有最小數(shù)量的線程可用; 使用adapter.ThreadPool屬性進行配置:adapter.ThreadPool.Sizeadapter.ThreadPool.SizeMax1. ICE運行時1. ICE運行時1.10 ice線程模型1.10.4 設(shè)計考慮不合理的線程池配置可能會導(dǎo)致嚴(yán)重的性能問題。設(shè)計應(yīng)用時可考慮如下一些問題:(1) 只有1個線程的線程池的影響. 一次只有一個消息能被分派。這樣做可以不必考慮線程安全問題

43、,但是它消除了可能的并行分派,這在多CPU的系統(tǒng)上將帶來性能瓶頸; .一次僅有一個AMI響應(yīng)可被處理。你必須增加客戶端線程池大小以便多個AMI回調(diào)能并發(fā)處理; .嵌套雙向調(diào)用將受到限制。單線程的情況下最多只能有1層雙向嵌套調(diào)用;需要注意:通信器的客戶端和服務(wù)端線程池缺省的最大線程數(shù)是1個,使用時需要注意。1. ICE運行時1. ICE運行時1.10 ice線程模型1.10.4 設(shè)計考慮(2) 使用多線程的線程池當(dāng)配置線程池支持多個線程時也就意味著ICE運行時會并發(fā)的分派操作調(diào)用以及并發(fā)的處理AMI回調(diào)。這雖然會增加線程安全問題上的設(shè)計考慮,但是它所帶來的可伸縮性和更高的吞吐量也是顯而易見的。具

44、體線程池最大線程數(shù)是多少也是需要精心考慮的。例如,超過實際處理器數(shù)量的線程數(shù)可增加系統(tǒng)的響應(yīng)性。但是過多的線程數(shù)也會起副作用。建議在真實使用環(huán)境下來測試系統(tǒng)最佳的線程數(shù)。 1. ICE運行時1. ICE運行時1.10 ice線程模型1.10.4 設(shè)計考慮(3) 序列化時的考慮當(dāng)使用多線程線程池時,線程調(diào)度的不確定性會導(dǎo)致調(diào)用分派順序可能和調(diào)用到來時的接收順序不一致。有些應(yīng)用不允許這種情況,例如一些事物處理服務(wù)必須保證順序。有兩種方式可以解決這個問題:1. 使用單線程的線程池;2. 使用Serialize屬性(poolname.Serialize)配置多線程的線程池來處理序列化請求。 在客戶端避

45、免并發(fā)調(diào)用也可以避免上述問題,但會降低客戶端的性能。 打開Serialize屬性會增加處理延遲減小服務(wù)吞吐量。如果服務(wù)端必須保證客戶端請求順序,一個比較好的做法是序列化配合使用異步分派排隊到來的請求,將請求排隊放入一個隊列,然后由其它線程來執(zhí)行這些請求。 1. ICE運行時1. ICE運行時1.10 ice線程模型1.10.5 嵌套調(diào)用 嵌套調(diào)用:一個Ice操作發(fā)生在另一個Ice操作的上下文中。 注意:如果有嵌套調(diào)用,則需要注意避免潛在的死鎖肯能。例如,調(diào)用時路徑出現(xiàn)環(huán)路。 這張圖中操作A嵌套雙向調(diào)用了操作B,但是操作B嘗試嵌套回調(diào)時發(fā)生死鎖。因為,通信器缺省最大線程數(shù)是1個,所以服務(wù)A中僅有

46、的一個線程正忙于等待操作B的調(diào)用完成,因此沒有線程來處理服務(wù)B的回調(diào)操作。這時客戶端因為服務(wù)A阻塞,所以它也被阻塞。 在這種場景下有多種方法可以避免死鎖發(fā)生: (1)增加服務(wù)A的線程池的最大線程數(shù)量; (2)使用單向調(diào)用; (3)另外再創(chuàng)建一個對象適配器用于回調(diào);(另外的適配器配置有自己的線程池) (4)操作A實現(xiàn)為異步分派和調(diào)用: 將操作A實現(xiàn)為AMD方式,調(diào)用操作B實現(xiàn)為AMI方式。這樣服務(wù)A中的線程不用一直 阻塞去等待操作B的完成。 1. ICE運行時1. ICE運行時1.10 ice線程模型1.10.5 嵌套調(diào)用是否使用嵌套調(diào)用:是否設(shè)計成嵌套調(diào)用需要考慮一些因素: (1)線程池的配置

47、是否能滿足嵌套調(diào)用要求; (2)雙向連接所帶來的復(fù)雜性,因此你必須小心處理線程的使用; (3)各通信模塊中的同步問題也需要考慮,為了同步所加入的鎖也可能導(dǎo)致死鎖。所以,在嵌套調(diào)用的情況下,跟蹤調(diào)用路徑來避免死鎖會變得很復(fù)雜。1. ICE運行時1. ICE運行時1.10 ice線程模型1.10.6 向用戶線程分派調(diào)用 缺省情況下操作調(diào)用和AMI回調(diào)以及操作分派所使用的線程都是Ice運行時線程池中的線程。這樣做很方便,不用考慮線程的創(chuàng)建和銷毀。 但是Ice運行時線程數(shù)量有限,當(dāng)運行時線程耗盡后將無法繼續(xù)接收新的調(diào)用和分派。 例如,我們的目前的服務(wù)端實現(xiàn)中使用了一個自己的線程池,所有到來的調(diào)用請求會

48、先放入一個請求隊列中,然后由服務(wù)端自己的線程池去處理請求。這樣,Ice運行時的線程池中始終有空閑線程可用于接收新的請求。virtual bool Dispatch(const CRpcDispatchResultPtr &pCallback, const std:string &strOperationName,const BYTE_VECTOR &oInStream)GetLogger().debug(Operation %s Dispatch, strOperationName.c_str();bool bOk = RequestHandlerMgr:get_mut

49、able_instance().AddRequest(pCallback, strOperationName, oInStream);if (!bOk)UnknownDispatch(pCallback, strOperationName, oInStream);return bOk;1. ICE運行時1. ICE運行時1.10 ice線程模型1.11 代理的使用及配置(Proxies) 代理對象能夠使得遠(yuǎn)程調(diào)用像本地調(diào)用一樣簡單。事實上,處理遠(yuǎn)程調(diào)用只是代理對象的眾多職責(zé)之一。 代理還封裝了連接遠(yuǎn)程對象所需的足夠信息,包括標(biāo)識、地址信息(傳輸端點)等。 代理方法還提供了訪問配置及連接信息的功

50、能,以及創(chuàng)建新代理對象的功能。代理負(fù)責(zé)所需的新連接的建立。 代理分成兩類: 直接代理其內(nèi)部保存有某個對象的標(biāo)識,以及它的服務(wù)器的運行地址;(ObjectIdent:tcp h p 9999)間接代理其內(nèi)部保存有某個對象的標(biāo)識,以及對象適配器名(object adapter name)(ObjectIdent或ObjectIdentAdapterName)。1. ICE運行時1.11 代理1.11.1 獲取代理字符串表示的代理: 通信器的stringToProxy方法可從代理的字符串標(biāo)識創(chuàng)建一個代理對象: Ice:ObjectPrx p = communicator-string

51、ToProxy(“ident:tcp p 5000”);代理屬性: 除了上述硬編碼方式表示代理對象,還可通過配置屬性將代理外部化。例如,可以定義一個屬性包含代理字符串標(biāo)識: MyApp.Proxy-ident:tcp p 5000可以使用通信器的propertyToProxy方法從配置屬性得到代理對象。1. ICE運行時1.11 代理例如: 配置文件中配置了代理 Hello.Proxy=hello:tcp -p 10000通信器初始化時加載了這個該配置文件 initDperties-load(configFile);使用通信器方法propertyToProxy創(chuàng)建代理HelloP

52、rx twoway = HelloPrx:checkedCast( communicator()-propertyToProxy(Hello.Proxy);1.11.1 獲取代理通過工廠方法創(chuàng)建代理 代理提供一些方法允許改變已有的代理的某些特性,得到新的代理。因為代理本身是不可變的,工廠方法會返回新的代理對象。 例如: ice_oneway方法返回一個單向調(diào)用代理對象。 注意:如果原代理的配置和新代理配置不一樣,則返回的是一個新代理對象實例。 checkCast和uncheckedCast方法也可以認(rèn)為是工廠方法,因為他們也會返回新代理對象。 HelloPrx twoway = HelloPr

53、x:checkedCast(communicator()-propertyToProxy(Hello.Proxy)-ice_twoway()-ice_timeout(-1)-ice_secure(false); if(!twoway) cerr argv0 : invalid proxy ice_oneway(); HelloPrx batchOneway = twoway-ice_batchOneway(); HelloPrx datagram = twoway-ice_datagram(); HelloPrx batchDatagram = twoway-ice_batchDatagram

54、();1. ICE運行時1.11 代理1.11.3 代理的端點 代理傳輸端點是位于客戶側(cè)的并等同于對象適配器的傳輸端點。代理傳輸端點標(biāo)識了同遠(yuǎn)程對象通信用的協(xié)議信息。例如:tcp h p 10000這個端點標(biāo)示一個遠(yuǎn)程對象,改對象可通過tcp協(xié)議連接,該對象處于主機上,端口10000。代理對象必須至少能獲取到一個端點。 直接代理對象可包含1個或多個端點: MyObject:tcp h p 10000:ssl h o 10001如果直接代理不含有-h項,則Ice運行時將使用屬性Ice.Default.Host。如果Ice.Default.Host也未定義,則localhost網(wǎng)絡(luò)接口將被使用。

55、間接代理只有對象標(biāo)識或還有適配器名,它使用定位服務(wù)來動態(tài)獲取傳輸端點。 MyObject或MyObjectAdapterName1. ICE運行時1.11 代理1.11.4 端點過濾 代理的配置決定了它的端點如何使用。例如,一個配置為安全通信的代理它的端點必須使用安全協(xié)議,如SSL。 如下表中列出了一些工廠方法返回的代理對象其端點必須根據(jù)該代理對象的配置來使用。1. ICE運行時1.11 代理1.11.4 端點過濾例如:Ice_secure()返回的代理對象只使用安全協(xié)議的端點.如果沒有正確協(xié)議的端點可用,則連接建立時會收到NoEndpointException異常。 1. ICE運行時1.1

56、1 代理1.11.5 缺省值與覆蓋 理解代理是如何受Ice配置屬性設(shè)置影響的是很重要的。相關(guān)屬性可分為兩類:缺省值和覆蓋值(defaults and overrides)。 缺省屬性缺省屬性 缺省屬性影響那些由Ice調(diào)用、stringToProxy或propertyToProxy創(chuàng)建的代理對象,不影響工廠方法創(chuàng)建的代理。 覆蓋屬性覆蓋屬性 設(shè)置覆蓋屬性將導(dǎo)致Ice運行時忽略與之對應(yīng)的代理設(shè)置而直接使用覆蓋屬性設(shè)置。例如:Ice.Override.Secure=1 指示Ice運行時只使用安全端點,相當(dāng)于對每個代理調(diào)用ice_secure(true)。但是這個屬性不會改變已存在的代理的設(shè)置,而是指

57、示Ice運行時使用安全端點而不去理會代理自身的安全設(shè)置。 1. ICE運行時1.11 代理1.12 Ice:Contextmodule Ice local dictionary Context; 上下文就是一個把串映射到串的詞典,或者從概念上說,上下文就是一系列名- 值對。 每當(dāng)有請求要發(fā)往服務(wù)器時,這個詞典的內(nèi)容(如果有的話)都會隨同請求一起整編,也就是說,如果客戶在上下文中放入一些名- 值對,并在發(fā)出調(diào)用時使用這個上下文,服務(wù)器就將能使用客戶所發(fā)送的這些名- 值對。 上下文提供了一種手段,可以把數(shù)量不限的參數(shù)從客戶發(fā)往服務(wù)器,而不必在操作的型構(gòu)中提到這些參數(shù)。例如:PersonPrx p

58、= .;Address a = .;Ice:Context ctx;ctxwrite policy = immediate;p-setAddress(a, ctx);/ 在服務(wù)端,Current c;Ice:Context:const_iterator i = c.ctx.find(write policy); 1. ICE運行時1.12 Ice:Context注意:通過使用Ice:Context,在處理每一個請求時,它們可以向服務(wù)端傳入一些上下文信息。上下文的設(shè)計用途是傳送簡單的token (比如事務(wù)標(biāo)識符),你應(yīng)該只把上下文用于這樣的目的,而不要把它用于其他目的。 例如,如果服務(wù)端設(shè)計上必

59、須接收上下文,但是它是無法強制客戶端調(diào)用時一定會傳入上下文的,如果客戶端沒有發(fā)送上下文信息,服務(wù)端可能無法工作或異常。1. ICE運行時1.13 具有超時的代理代理方法Ice:ObjectPrx ice_timeout(Ice:Int t) const;會根據(jù)一個已有代理創(chuàng)建一個具有超時的代理,參數(shù)t以毫秒為單位,-1表示沒有超時。如果在超時代理上調(diào)用的操作沒有在超時時間內(nèi)完成,客戶端會收到異常。注意:連接的建立和關(guān)閉也有超時: ConnectTimeoutException: 連接無法在制定時間內(nèi)建立; CloseTimeoutException:連接無法在指定時間內(nèi)關(guān)閉。同樣支持覆蓋屬性來

60、設(shè)置超時時間: Ice.Override.Timeout Ice.Override.ConnectTimeout(設(shè)置了覆蓋參數(shù)后,代理自身的超時設(shè)置會被覆蓋)1. ICE運行時1.13具有超時的代理注意: 這些超時是“軟”超時,也就是說,它們不是精確的、實時的超時(精確度受制于底層操作系統(tǒng)的能力)。 Ice run time把超時當(dāng)作是嚴(yán)重的出錯:例如,超時會導(dǎo)致客戶端的連接關(guān)閉。 超時應(yīng)該被用于防止客戶在“服務(wù)器發(fā)生錯誤”的情況下無限期地阻塞; 1. ICE運行時1.14 單向調(diào)用單向調(diào)用客戶端發(fā)送調(diào)用后不關(guān)心任何服務(wù)端回應(yīng),服務(wù)端也不會給客戶端任何回應(yīng),客戶端不關(guān)心調(diào)用是否成功。單向調(diào)用(客戶端側(cè)) 在客戶端,調(diào)用的發(fā)送是通過把請求寫到客戶的本地傳輸緩沖區(qū)來完成的;一旦本地傳輸機制接受了調(diào)用,調(diào)用就會完成,并把

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論