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单例服务的基本概念就为大家介绍到这里。