一步一步學remoting之二:啟用模式
遠端物件的啟用模式分服務端啟用和客戶端啟用兩種,(也就是物件分服務端啟用物件或者說是知名物件和客戶端啟用物件兩種)先看看msdn怎麼描述服務端啟用的:
伺服器啟用的物件是其生存期由伺服器直接控制的物件。伺服器應用程式域只有在客戶端在物件上進行方法呼叫時才建立這些物件,而不會在客戶端呼叫 new 或 activator.getobject 時建立這些物件;這節省了僅為建立例項而進行的一次網路往返過程。客戶端請求伺服器啟用的型別例項時,只在客戶端應用程式域中建立乙個**。然而,這也意味著當您使用預設實現時,只允許對伺服器啟用的型別使用預設建構函式。若要發布其實例將使用帶引數的特定建構函式建立的型別,可以使用客戶端啟用或者動態地發布您的特定例項。
伺服器啟用的物件有兩種啟用模式(或 wellknownobjectmode 值):singleton 和 singlecall。
singleton 型別任何時候都不會同時具有多個例項。如果存在例項,所有客戶端請求都由該例項提供服務。如果不存在例項,伺服器將建立乙個例項,而所有後繼的客戶端請求都將由該例項來提供服務。由於 singleton 型別具有關聯的預設生存期,即使任何時候都不會有乙個以上的可用例項,客戶端也不會總接收到對可遠端處理的類的同一例項的引用。
singlecall 遠端伺服器型別總是為每個客戶端請求設定乙個例項。下乙個方法呼叫將改由其他例項進行服務。從設計角度看,singlecall 型別提供的功能非常簡單。這種機制不提供狀態管理,如果您需要狀態管理,這將是乙個不利之處;如果您不需要,這種機制將非常理想。也許您只關心負載平衡和可伸縮性而不關心狀態,那麼在這種情況下,這種模式將是您理想的選擇,因為對於每個請求都只有乙個例項。如果願意,開發人員可以向 singlecall 物件提供自己的狀態管理,但這種狀態資料不會駐留在物件中,因為每次呼叫新的方法時都將例項化乙個新的物件標識。
首先對於服務端啟用的兩種模式來做乙個試驗,我們把遠端物件做如下的修改:
using
system;
namespace
remoteobject
public
intcount()}}
=(remoteobject.myobject)activator.getobject(
typeof
"serviceurl
"第一次開啟客戶端的時候顯示1,第二次開啟的時候顯示2,類推……由此驗證了singleton 型別任何時候都不會同時具有多個例項。如果存在例項,所有客戶端請求都由該例項提供服務。如果不存在例項,伺服器將建立乙個例項,而所有後繼的客戶端請求都將由該例項來提供服務。
把伺服器端的config修改一下:
<
wellknown
type
="remoteobject.myobject,remoteobject"
objecturi
="remoteobject.myobject"
mode
="singlecall"
/>
(這裡注意大小寫,大寫的c)
再重新執行服務端和客戶端,開啟多個客戶端發現始終顯示1。由此驗證了singlecall 型別對於每個客戶端請求都會重新建立例項。下乙個方法呼叫將由另乙個伺服器例項提供服務。
下面再說一下客戶端的啟用模式,msdn中這麼寫:
客戶端啟用的物件是其生存期由呼叫應用程式域控制的物件,正如物件對於客戶端是本地物件時物件的生存期由呼叫應用程式域控制一樣。對於客戶端啟用,當客戶端試圖建立伺服器物件的例項時發生乙個到伺服器的往返過程,而客戶端**是使用物件引用 (objref) 建立的,該物件引用是從在伺服器上建立遠端物件返回時獲取的。每當客戶端建立客戶端啟用的型別的例項時,該例項都將只服務於該特定客戶端中的特定引用,直到其租約到期並**其記憶體為止。如果呼叫應用程式域建立兩個遠端型別的新例項,每個客戶端引用都將只呼叫從其中返回引用的伺服器應用程式域中的特定例項。
理解一下,可以歸納出
1、客戶端啟用的時間是在客戶端請求的時候,而服務端啟用遠端物件的時間是在呼叫物件方法的時候
遠端物件修改如下:
using
system;
namespace
remoteobject
public
intadd(
inta,
intb)
public
intcount()}}
服務端配置檔案:
<
configuration
>
<
system
.runtime.remoting
>
<
name
="remoteserver"
>
<
service
>
<
activated
type
="remoteobject.myobject,remoteobject"
/>
service
>
<
channels
>
<
channel
ref="tcp"
port
="9999"
/>
channels
>
>
system.runtime.remoting
>
configuration
>
客戶端程式:
using
system;
namespace
remoteclient
);//
console.readline();}}
}客戶端配置檔案:
<
configuration
>
<
>
<
add
key="serviceurl"
value
="tcp://localhost:9999/remoteserver"
/>
>
configuration
>
=(remoteobject.myobject)activator.createinstance(
typeof
(remoteobject.myobject),
newobject
,new
object
毫無疑問,我們執行客戶端發現輸出的是11而不是1了。
3、通過上面的例子,我們執行多個客戶端發現出現的永遠是11,因此,客戶端啟用模式一旦獲得客戶端的請求,將為每乙個客戶端都建立乙個例項引用。
總結:1、remoting支援兩種遠端物件:知名的和客戶啟用的。知名的遠端物件使用了uri作為標識,客戶程式使用這個uri來訪問那些遠端物件,也正式為什麼稱作知名的原因。對知名的物件來說2種使用模式:singlecall和singleton,對於前者每次呼叫都會新建物件,因此物件是無狀態的。對於後者,物件只被建立一次,所有客戶共享物件狀態,因此物件是有狀態的。另外一種客戶端啟用物件使用類的型別來啟用,uri再後台被動態建立,並且返回給客戶程式。客戶啟用物件是有狀態的。
2、對於singleton物件來說需要考慮伸縮性,singleton物件不能在多個伺服器上被部署,如果要跨伺服器就不能使用singleton了。
備註:個人習慣原因,在我的例子中服務端的配置都是用config檔案的,客戶端的配置都是基本用程式方式的
使用配置檔案的優點:無需重新編譯就可以配置通道和遠端物件,編寫的**量比較少
使用程式定製的優點:可以獲得執行期間的資訊,對程式除錯有利。
樓主對於singleton 和singlecall 的理解似乎是錯的,完全搞反了,請你再仔細看看msdn上面的介紹:
singleton :「singleton 物件是這樣的物件:無論該物件有多少個客戶端,總是只有乙個例項,且該物件具有預設的生存期。」
singlecall :「singlecall 物件時,系統將為每個客戶端方法呼叫建立乙個新物件。」
而你前面第一次講到這2個概念的時候說得都是只有1次例項化,(在第4,5段開始),
後面singlecall試驗完了,總結的時候也是說的1個例項,在後面客戶啟用同樣也是說得1個例項
所以你對於singlecall的理解是錯誤的,他應該是每次呼叫都產生新的例項。
以前見過一本書,這樣說:「singlecall是單調用物件,每次呼叫都被例項化(會有多個例項),並且最後會被無用單元收集器銷毀。singleton 是單元素物件,只是在第一次呼叫的時候例項化,然後留在那裡直到最後乙個客戶把他釋放」。
建議你這樣理解就不會亂了。
一步一步學Remoting之二 啟用模式
遠端物件的啟用模式分服務端啟用和客戶端啟用兩種,也就是物件分服務端啟用物件或者說是知名物件和客戶端啟用物件兩種 先看看msdn怎麼描述服務端啟用的 伺服器啟用的物件是其生存期由伺服器直接控制的物件。伺服器應用程式域只有在客戶端在物件上進行方法呼叫時才建立這些物件,而不會在客戶端呼叫 new 或 ac...
一步一步學Remoting之二 啟用模式
遠端物件的啟用模式分服務端啟用和客戶端啟用兩種,也就是物件分服務端啟用物件或者說是知名物件和客戶端啟用物件兩種 先看看msdn怎麼描述服務端啟用的 伺服器啟用的物件是其生存期由伺服器直接控制的物件。伺服器應用程式域只有在客戶端在物件上進行方法呼叫時才建立這些物件,而不會在客戶端呼叫 new 或 ac...
一步一步學Remoting之二 啟用模式
文 遠端物件的啟用模式 遠端物件的啟用模式分服務端啟用和客戶端啟用兩種,也就是物件分服務端啟用物件或者說是知名物件和客戶端啟用物件兩種 服務端啟用 先看看msdn怎麼描述服務端啟用的 伺服器啟用的物件是其生存期由伺服器直接控制的物件。伺服器應用程式域只有在客戶端在物件上進行方法呼叫時才建立這些物件,...