服務實例模式
真正實現邏輯是在Service instance中發(fā)生的,client調用最終產生Service Instance的過程叫Activation(激活)。在Remoting中我們有兩種Activation方式:Server Activation(Singleton和SingleCall),Client Activation。
實際上對WCF也具有相似的Activation。不過WCF不僅僅創(chuàng)建對應的Service Instance,而且還構建相關的Context, 我們把這些統稱為Instance Context。不同的Activation方式在WCF中體現為的Instance context model。不同的Instance Context Mode體現為Proxy、Service 調用和Service Instance之間的對應關系??梢赃@么說,Instance Context Mode決定著不同的Session表現。在WCF中,支持以下3中不同級別的Instance Context Mode:
1>.單調服務(Per-Call Service):每次的客戶端請求分配一個新的服務實例。類似于Net Remoting的SingleCall模式;
2>.會話服務(Sessionful Service):則為每次客戶端連接分配一個服務實例。類似于Net Remoting的客戶端激活模式;
WCF的默認實例模式是PerSession,不同的實例模式,對Session的支持也不同。當然,首先Session的支持是通過Sessionful Channel來實現的,所以如果選擇了不支持Session的綁定,那其他都是沒用的。比如BasicHttpBinding就不支持Session)。
各種實例模式的應用場合?
PerCall
在傳統模式C/S模式的應用程序中,通常情況下存在這樣的問題:客戶端請求服務端之后,服務端并不是馬上對處理客戶端請求時需要的資源進行釋放,服務端往往自作多情的認為客戶端一定是個老主顧,會時不時來消費一番??伤麉s沒想到,有的時候,客戶端是個昧良心的家伙,就算服務端再怎么獻殷勤,客戶端也不買賬。而對于一些非常珍貴的資源,比如數據庫連接,文件,圖像,通訊端口等。服務這種做法往往會使這些資源長期被不來消費的客戶端空閑占用,當有新的請求真正要用使用他們的時候,卻因為資源耗盡而無法處理。這樣對服務端就得不償失了,而PerCall就是對上面提到問題的一種解決方案。它采用類似快餐式的經營方式,當一個請求操作來到的時候,再創(chuàng)建服務對象,申請必要資源,而當操作完畢之后,立即銷毀對象并釋放資源,留給下一個請求。這就可能大大提高服務端的吞吐能力。而且WCF中默認的實例創(chuàng)建模式就是這種。
PerSession
正如上面對PerCall的描述所說,PerSession與傳統的C/S模式應用程序非常相似,它能在服務端和客戶端維護狀態(tài),當一個服務對象創(chuàng)建之后不會馬上銷毀,而是等待客戶端再次來消費它,那這種的壞處也說過了,可能會浪費寶貴的服務資源,可它也是有好處的。比如它能夠保持連接和維護狀態(tài),這在要求有回調的情況下特別重要,因為如果服務端連哪個家伙點的菜都忘記了怎么為客人上菜呢?還有一種情況,服務端操作不需要比較多的資源或者占用的資源也不寶貴的情況下,而卻與客戶端在不同的網絡中,它們之間進行一次連接可費了老勁,這時也適用于此種實例模式。
Single
大家經常去理發(fā)吧?去那大的理發(fā)店,里面的理發(fā)師這家伙這個多,你隨便找個就能幫你料理了,可兄弟我比較窮酸,每次都去小區(qū)理發(fā)店,里面連洗頭,在理發(fā)就1位師傅,小區(qū)人可不少,僧多飯少,你說咱進去得排隊吧。人家理發(fā)的時候,咱就得邊上看著,得人家都整完了,嘿,咱就洗頭,理發(fā),吹風來個一條龍。Single模式就像上面提到的小區(qū)理發(fā)店,人家從早晨一開業(yè),理發(fā)師就給你準備好了,您也甭挑蹦撿。伺候完你,他再伺候別人,為何要這么做?其實道理也很簡單,如果理發(fā)師不喝水,不吃飯,不用管食宿,不用工錢,不會唧唧歪歪,那理發(fā)店老板娘肯定請1萬個過來??涩F實不是那樣子的,是這些理發(fā)師都要吃喝拉撒睡,還要拿俸祿,就一個幾十平米的小理發(fā)店,估計給老板娘賣了也不夠他們的呢。
使用不同的實例模式,需要注意的有哪些?
1 對于PerCall模式,一定要記住,如果服務對象中的數據沒有固化,并且不是靜態(tài)變量,那它每次操作都會被重新初始化。
2 對于PerSession模式,第一要清楚有些Binding是不能用于此種模式的,具體什么可用,什么不能用,可以查閱http://www.cnblogs.com/jillzhang/archive/2008/02/03/1063406.html 。另外,PerSession模式并不是代表狀態(tài)會自動維護,那些被設置了IsTerminating=True的操作完成的時候,也會釋放資源和銷毀對象。即使不是Ture,那如果客戶端長時間不與服務端聯系,達到服務端最大忍耐限度,服務端也會變心。
3 對于Single模式,既然例外就它老哥一個,就簡單得多了,它能保持服務對象中的非靜態(tài)全局變量。但是特別要注意的是,如果在這種模式下的話,要特別注意線程安全的問題,讓10個人同時讓一個理發(fā)師傅來服務。
3總結
A.首先當binding不支持session時候,所有設置都不會支持Session;單調和會話模式都是調用不同的實例,只有單例模式調用相同實例。
B.當我們設置SessionModel為NotAllowed(TCP綁定下,不可以設置SessionModel為NotAllowed,否則會出現這個錯誤“協定不允許會話,但是綁定“NetTcpBinding”不支持數據圖,或者因配置不正確而無法支持數據圖。”)時(其實等同于A)
l 如果是單調模式,不存在SessionId,每次調用不同實例
l 如果是會話模式,不存在SessionId,每次調用不同實例(實際就等于單調模式)
l 如果是單例模式,不存在SessionId,調用相同實例
C.設置SessionModel為Allowed/Required
l 如果是tcpBinding,所有Proxy的SessionId相同,下面討論mexHttpBinding
l 單調模式:只有同一個Proxy的SessionId相同,實例不同
l 會話模式:同一個Proxy的實例SessionId相同,同一個Proxy的實例相同
l 單例模式:同一個Proxy的實例SessionId相同,所有Proxy實例相同
WCF分布式開發(fā)步步為贏(9):WCF服務實例激活類型編程與開發(fā)
我的WCF之旅(8):WCF中的Session和Instancing Management
Programming WCF Services翻譯筆記(七)
并發(fā)
當一個消息到達時,服務模型會從線程池中取出一個線程來傳送消息。這時,如果多個客戶端調用相同的服務,多個并發(fā)請求會同時到達該服務。PerCall服務會為每個請求分配一個新的服務對象。PerSession服務,同一個服務對象從同一個客戶端接收請求。對于Single實例模式,所有的客戶端請求都被發(fā)送到同一個單利服務對象。在此基礎上,當客戶端是多線程的時候,PerSession服務就有并發(fā)訪問的肯那個,而對于Single服務,該危險永遠是存在的。
默認情況下,無論哪種實例化模式,只有一個請求線程可以獲準訪問所有服務對象。這是設置ServiceBehaviorAttribute的ConcurrencyMode屬性,默認是Single。他有三個值可選:
l Single:一個一的請求線程能夠在某一特定時間訪問服務對象
l Reentrant(重入):一個單一的請求線程能夠反問這些服務對象,但線程可以退出這項服務,并重新輸入而不會死鎖。
當一個服務是回調給客戶的時候,重入模式是必要的,除非這個回調的是一個單向操作。因為,客戶調用服務并等待響應??蛻粼谄湔{用線程中受阻,直到調用返回。服務發(fā)送一個回調給客戶并等待響應。這肯定會發(fā)生死鎖。設置重入模式,可以避免這種問題,從服務到客戶端的調用會返回給服務實例而不會引起死鎖。
l Multiple:多個請求線程能夠訪問這些服務對象和共享資源。
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Single)]
public class CalculateService : ICalculate
限流
限流“允許開發(fā)者限制客戶端連接數以及服務的負荷。限流可以避免服務的最大化,以及分配與使用重要資源的最大化。引入限流技術后,一旦超出配置的設置值,WCF就會自動地將等待處理的調用者放入到隊列中,然后依次從隊列中取出。在隊列中等待處理調用時,如果客戶端的調用超時,客戶端就會獲得一個TimeoutException異常。每個服務類型都可以應用限流技術,也就是說,它會影響到服務的所有實例以及服務類型的所有終結點。實現方式是為限流與服務使用的每個通道分發(fā)器建立關聯。
為了增加服務的吞吐量,必須允許進行多重并發(fā)調用。不管哪種實例模式,服務器資源一般沒有處理無線數量的并發(fā)請求的能力。WCF提供了一個限流行為來管理服務器負載和資源消耗。該行為具有以下屬性:
MaxConcurrentCalls(一個服務實例可以處理的所有并發(fā)請求數量)、 MaxConcurrentSessions(限制服務允許的活動會話的數量)、
MaxConcurrentInstances(限定某一特定時刻可以分配的服務實例數量),它們分別的默認值為16,10和Int.MaxValue。
<system.serviceModel>
<services>
<service name = "MyService"
behaviorConfiguration = "ThrottledBehavior"> ... </service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name =
"ThrottledBehavior">
<serviceThrottling
maxConcurrentCalls = "12"
maxConcurrentSessions = "34"
maxConcurrentInstances = "56" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
WCF并沒有提供關于限流的特性。但實現該特性的方法非常簡單,如下內容是我定義的關于限流的特性,本書并沒有提供:
public class ServiceThrottlingAttribute : Attribute, IServiceBehavior
{
private ServiceThrottlingBehavior throttle;
public ServiceThrottlingAttribute(
int maxConcurrentCalls,
int maxConcurrentInstances,
int maxConcurrentSessions)
{
this.throttle = new ServiceThrottlingBehavior();
throttle.MaxConcurrentCalls = maxConcurrentCalls;
throttle.MaxConcurrentInstances = maxConcurrentInstances;
throttle.MaxConcurrentSessions = maxConcurrentSessions;
}
#region IServiceBehavior Members
void IServiceBehavior.AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{ }
void IServiceBehavior.ApplyDispatchBehavior
(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
ServiceThrottlingBehavior currentThrottle =
serviceDescription.Behaviors.Find<ServiceThrottlingBehavior>();
if (currentThrottle == null)
{
serviceDescription.Behaviors.Add(this.throttle);
}
}
void IServiceBehavior.Validate(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{ }
#endregion
}
定義的ServiceThrottlingAttribute特性繼承了Attribute,并實現了IServiceBehavior接口。在特性內,則使用了ServiceThrottlingBehavior類,以設置限流的相關值。如果要配置服務的限流值,就可以應用該特性,例如:
[ServiceThrottling(12, 34, 56)]
class MyService : IMyContract,IDisposable
{
public void MyMethod( )
{
ChannelDispatcher dispatcher =
OperationContext.Current.Host.ChannelDispatchers[0]
http://www.cnblogs.com/wayfarer/archive/2007/11/12/956561.html