WCF單例服務中可擴展性認識
WCF開發工具的出現,為開發人員帶來了非常大的好處。我們今天將會通過這篇文章中介紹的內容為大家充分講解一下關于WCF單例服務的基本內容,從而使朋友們可以加深對WCF工具的應用。#t#
對并發服務調用請求的處理是WCF最基本要求,為了提供服務的響應能力,WCF會在不同的線程中處理并發請求。在單例模式下,服務實例是唯一的,也就是說相同的服務實例會同時被多個線程并發地訪問。在默認的情況下,多個線程以同步的方式訪問WCF單例服務對象,也就是說,在某個時刻,最多只會有一個線程在使用服務實例。如果一個服務操作需要1秒,那么在一分鐘內最多只能處理60個服務調用請求。倘若客戶端采用默認的超時時限(1分鐘),對于60個并發地服務調用請求,至少會有一個服務調用會失敗。這極大地降低了WCF服務的可擴展性、響應能力和可用性。
為了讓讀者對WCF單例服務的低可擴展性有一個深刻的認識,我寫了一個極端的案例。從這個案例演示中,讀者會清晰地認識到提供一個相同的功能,采用單調模式和單例模式,對客戶端影響的差別有多大。本案例同樣沿用計算服務的例子,Add方法中通過使線程休眠5秒模擬一個耗時的服務操作,下面是服務的定義,采用單調實例上下文模式。
- [ServiceBehavior(InstanceContextModeInstanceContextMode =
InstanceContextMode.PerCall)]- public class CalculatorService : ICalculator
- {
- public double Add(double x, double y)
- {
- Thread.Sleep(5000);
- return x + y;
- }
- }
在客戶端,通過ThreadPool模擬5個并發的客戶端,在Add操作調用成功后輸出當前的時間,從而檢驗服務的響應能力。
- for (int i = 0; i <
- i++)
- {
- ThreadPool.QueueUserWorkItem(delegate
- {
- using (ChannelFactory<ICalculator> channelFactory =
new ChannelFactory<ICalculator>("calculatorservice"))- {
- ICalculator calculator = channelFactory.CreateChannel();
- Console.WriteLine("{3}: x + y = {2} when x = {0} and y = {1}",
1, 2, calculator.Add(1, 2), DateTime.Now); }- });
- }
從客戶端輸出結果我們可以看出,對于5個并發的服務調用均得到了及時的相應,這是我們希望看到的結果。
- 3/8/2009 08:03:17 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:03:17 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:03:17 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:03:18 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:03:18 : x + y = 3 when x = 1 and y = 2
但是,如果將實例上下文模式換成是InstanceContextMode.Single,情況就完全不一樣了。從最終的輸出結果可以看出,客戶端得到執行結果的間隔為5s,由此可知服務操作在服務端是以同步的方式執行的。
- [ServiceBehavior(InstanceContextModeInstanceContextMode =
InstanceContextMode.Single)]- public class CalculatorService : ICalculator, IDisposable
- {
- //省略實現
- }
輸出結果:
- 3/8/2009 08:03:25 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:03:30 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:03:35 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:03:40 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:03:45 : x + y = 3 when x = 1 and y = 2
WCF通過并發模式(Concurrency Mode)表示多線程訪問WCF單例服務對象的方式,而并發模式作為一種服務行為可以通過ServiceBehaviorAttribute特性進行設定。WCF通過ConcurrencyMode枚舉來表示不同形式的并發模式,三個枚舉值Single、Reentrant和Multiple分別表示單線程、重入和多線程三種并發模式。關于并發和并發模式,將在本書的下一卷予以詳細講解,在這里就不再作重復介紹了。ConcurrencyMode在ServiceBehaviorAttribute的定義如下:
- [AttributeUsage(AttributeTargets.Class)]
- public sealed class ServiceBehaviorAttribute :
Attribute, IServiceBehavior- {
- //其他成員
- public ConcurrencyMode ConcurrencyMode { get; set; }
- }
- public enum ConcurrencyMode
- {
- Single,
- Reentrant,
- Multiple
- }
ConcurrencyMode.Single是默認采用的并發模式,這正是上面的例子中服務操作同步執行的根本原因。為了讓服務操作異步地執行,從未提供服務的響應能力,我們只須要通過ServiceBehaviorAttribute將并發模式設為ConcurrencyMode.Multiple就可以了。
- [ServiceBehavior(InstanceContextModeInstanceContextMode =
InstanceContextMode.Single, ConcurrencyModeConcurrencyMode =
ConcurrencyMode.Multiple)]- public class CalculatorService : ICalculator, IDisposable
- {
- //省略實現
- }
輸出結果:
- 3/8/2009 08:05:05 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:05:05 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:05:05 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:05:05 : x + y = 3 when x = 1 and y = 2
- 3/8/2009 08:05:06 : x + y = 3 when x = 1 and y = 2
如果將并發模式設為ConcurrencyMode.Multiple,意味著同一個服務實例在多個線程中被并發執行。當我們操作一些數據的時候,須要根據具體的情況考慮是否要采用一些加鎖機制來確保狀態的同步性。
WCF單例服務的基本概念就為大家介紹到這里。