WCF学习之:实例上下文模式和并发模式的性能影响
2009-09-23 14:36
411 查看
实例上下文模式和并发模式的性能影响
Windows Communication Foundation (WCF) 应用程序的性能取决于许多不同的因素。应用程序设计、实例化模式、并发模式、传输、绑定设置和限制设置都会影响应用程序的性能。InstanceContextMode 和 ConcurrencyMode 设置彼此交互,对 WCF 应用程序性能会有很大影响。本主题讨论这两个设置如何影响 WCF 服务性能。在讨论这两个设置如何影响 WCF 之前,先简单说明一下其中每个设置的作用。
Single - 为所有客户端调用分配一个服务实例。
PerCall – 为每个客户端调用分配一个服务实例。
PerSession – 为每个客户端会话分配一个服务实例。
InstanceContextMode 的默认设置为 PerSession。
有关 InstanceContextMode 的更多信息,请参见:
InstanceContextMode 枚举
MSDN 杂志主页,2008 年 6 月版(可能为英文网页)
如何:控制服务实例化
Single - 一次可以有一个线程进入服务。
Reentrant - 一次可以有一个线程进入服务,但允许回调。
Multiple - 一次可以有多个线程进入服务。
ConcurrencyMode 的默认设置为 Single。默认选择此值是为了让开发人员无需考虑同步问题。有关 ConcurrencyMode 的更多信息,请参见:ConcurrencyMode
将 InstanceContextMode 设置为 Single 的原因很多,其中包括:
创建服务实例需要大量的处理工作。当多个客户端访问服务时,仅允许创建一个服务实例可以降低所需处理量。
一个服务实例可以创建多个对象。将 ConcurrencyMode 设置为 Single 可以降低垃圾回收成本,因为不必为每个调用创建和销毁服务创建的对象。
通过将 ConcurrencyMode 设置为 Single,可以在多个客户端之间共享服务实例。
如果 ConcurrencyMode 和 InstanceContextMode 均设置为 Single,则一次只允许一个客户端调用通过。如果有大量客户端,这可能会导致较大的瓶颈。
将 InstanceContextMode 设置为 Single 并将 ConcurrencyMode 设置为 Reentrant 的性能特征与将 ConcurrencyMode 设置为 Single 时相同。这是因为,一次仅允许一个客户端线程进入服务。
InstanceContextMode 设置为 PerCall 时,将为每个客户端调用创建一个新服务实例上下文(默认情况下,这表示一个新服务实例),并在客户端调用完成时销毁该实例。由于服务实例仅在进行调用时可 用,因此在调用完成时,会释放它们可能访问的所有资源。由于为每个调用分配一个新服务实例,因此会产生一些开销。但是,由于每个客户端都获取自己的服务实 例,因此不存在同步问题。当大量客户端调用同时发生时,将创建大量的服务实例。遇此情形时,务必使服务实例仅分配其正常工作所需的那些资源。
如果 ConcurrencyMode 设置为 Multiple,则多个客户端调用可以通过,但开发人员需负责手动同步对共享数据的所有访问。这意味着,一次只有一个线程可以访问共享数据,从而导致访问共享数据的所有调用顺序排队等候。这违背了将 ConcurrencyMode 设置为 Multiple 的初衷。
在 InstanceContextMode 设置为 PerCall 时,ConcurrencyMode 设置对吞吐量没有影响。每个客户端调用都获取自己的服务实例,因此每个服务实例只有一个调用到其中的线程。在 InstanceContextMode 设置为 PerSession 时,每个会话都获取自己的服务实例。有关 会话的更多信息,请参见使用会话(可能为英文网页)。使用 PerSession 时,必须使用支持会话的绑定。下表显示系统提供的哪些绑定支持会话。默认会话设置括在圆括号中。
有关 系统定义的哪些绑定支持会话的更多信息,请参见系统提供的绑定和配置系统提供的绑定。使用会话时,默认情况下每个客户端代理都获取自己的专用服务实例。来自该代理的所有调用都由同一服务实例处理。单个客户端可以创建两个不同的代理,在这种情况下将创建两个服务实例。两个代理可以共享同一会话。有关更多信息,请参见 ,请参见 InstanceContextSharing 示例。
如果 InstanceContextMode 设置为 PerSession 且 ConcurrencyMode 设置为 Single,则每个代理都获取自己的服务实例。由于一次仅允许一个线程进入服务实例,因此单个代理发出的对服务实例的所有并发调用将顺序排队等候。由于一次仅允许一个线程进入服务实例,因此在该线程退出之前,所有其他调用都将阻塞。如果有大量客户端同时发出调用,这将导致瓶颈。
如果 InstanceContextMode 设置为 PerSession 且 ConcurrencyMode 设置为 Multiple,则每个代理都获取自己的服务实例,且允许并发调用进入服务实例。因此,开发人员必须手动同步对共享数据的所有访问。同样,这会导致对共享数据的访问顺序排队等候,并降低性能,其原因与将 ConcurrencyMode 设置为 Single 时相同。
对于轻型服务实例,Single 和 PerCall 实例上下文模式之间的吞吐量差异不是很大(约为 8%)。
四台客户端计算机用于向 WCF 服务发出调用。向服务发出的每个调用将 1 到 100 个对象传递给服务操作,具体取决于正在执行的测试。每个对象都包含一个订单、有关采购者的信息和要采购的项。
测 试重点是 WCF 技术的服务器吞吐量。这定义为每秒完成的操作数。一个操作是一个请求和答复消息,服务几乎不进行处理。一个要了解的重点是,业务逻辑决定构造良好的 SOA 解决方案中的服务成本。通过省去服务上的业务逻辑处理,仅度量消息传递基础结构的成本。有些测试要求实现服务的类执行某些其他处理。对于这些测试,在服务 类的构造函数中放置了一些逻辑,以生成一组质数。每个测试运行 3 次,然后计算吞吐量的平均值。
下面的代码演示由用于生成性能数据的 WCF 服务实现的接口。
下面的代码演示服务的实现。
服务自承载在控制台应用程序中。下面的代码演示如何承载服务。
客户端应用程序也是一个控制台应用程序。下面的代码演示如何实现客户端。
文章来自微软MSDN: http://msdn.microsoft.com/zh-cn/library/cc681240.aspx
Windows Communication Foundation (WCF) 应用程序的性能取决于许多不同的因素。应用程序设计、实例化模式、并发模式、传输、绑定设置和限制设置都会影响应用程序的性能。InstanceContextMode 和 ConcurrencyMode 设置彼此交互,对 WCF 应用程序性能会有很大影响。本主题讨论这两个设置如何影响 WCF 服务性能。在讨论这两个设置如何影响 WCF 之前,先简单说明一下其中每个设置的作用。
实例上下文模式
InstanceContextMode 控制在响应客户端调用时,如何分配服务实例。InstanceContextMode 可以设置为以下值:Single - 为所有客户端调用分配一个服务实例。
PerCall – 为每个客户端调用分配一个服务实例。
PerSession – 为每个客户端会话分配一个服务实例。
InstanceContextMode 的默认设置为 PerSession。
有关 InstanceContextMode 的更多信息,请参见:
InstanceContextMode 枚举
MSDN 杂志主页,2008 年 6 月版(可能为英文网页)
如何:控制服务实例化
并发模式
ConcurrencyMode 控制一次允许多少个线程进入服务。ConcurrencyMode 可以设置为以下值之一:Single - 一次可以有一个线程进入服务。
Reentrant - 一次可以有一个线程进入服务,但允许回调。
Multiple - 一次可以有多个线程进入服务。
ConcurrencyMode 的默认设置为 Single。默认选择此值是为了让开发人员无需考虑同步问题。有关 ConcurrencyMode 的更多信息,请参见:ConcurrencyMode
实例上下文模式、并发模式和性能
InstanceContextMode 和 ConcurrencyMode 设置可以相互影响,因此了解它们如何影响性能时,必须同时查看这两个设置。例如,将 InstanceContextMode 设置为 PerCall 时,会忽略 ConcurrencyMode 设置。这是因为,每个客户端调用都将路由到新的服务实例,因此一次只会有一个线程在服务实例中运行。将 InstanceContextMode 设置为 Single 时,仅创建一个服务实例,因此 ConcurrencyMode 会影响应用程序的吞吐量。将 InstanceContextMode 设置为 Single 的原因很多,其中包括:
创建服务实例需要大量的处理工作。当多个客户端访问服务时,仅允许创建一个服务实例可以降低所需处理量。
一个服务实例可以创建多个对象。将 ConcurrencyMode 设置为 Single 可以降低垃圾回收成本,因为不必为每个调用创建和销毁服务创建的对象。
通过将 ConcurrencyMode 设置为 Single,可以在多个客户端之间共享服务实例。
如果 ConcurrencyMode 和 InstanceContextMode 均设置为 Single,则一次只允许一个客户端调用通过。如果有大量客户端,这可能会导致较大的瓶颈。
将 InstanceContextMode 设置为 Single 并将 ConcurrencyMode 设置为 Reentrant 的性能特征与将 ConcurrencyMode 设置为 Single 时相同。这是因为,一次仅允许一个客户端线程进入服务。
InstanceContextMode 设置为 PerCall 时,将为每个客户端调用创建一个新服务实例上下文(默认情况下,这表示一个新服务实例),并在客户端调用完成时销毁该实例。由于服务实例仅在进行调用时可 用,因此在调用完成时,会释放它们可能访问的所有资源。由于为每个调用分配一个新服务实例,因此会产生一些开销。但是,由于每个客户端都获取自己的服务实 例,因此不存在同步问题。当大量客户端调用同时发生时,将创建大量的服务实例。遇此情形时,务必使服务实例仅分配其正常工作所需的那些资源。
如果 ConcurrencyMode 设置为 Multiple,则多个客户端调用可以通过,但开发人员需负责手动同步对共享数据的所有访问。这意味着,一次只有一个线程可以访问共享数据,从而导致访问共享数据的所有调用顺序排队等候。这违背了将 ConcurrencyMode 设置为 Multiple 的初衷。
在 InstanceContextMode 设置为 PerCall 时,ConcurrencyMode 设置对吞吐量没有影响。每个客户端调用都获取自己的服务实例,因此每个服务实例只有一个调用到其中的线程。在 InstanceContextMode 设置为 PerSession 时,每个会话都获取自己的服务实例。有关 会话的更多信息,请参见使用会话(可能为英文网页)。使用 PerSession 时,必须使用支持会话的绑定。下表显示系统提供的哪些绑定支持会话。默认会话设置括在圆括号中。
绑定 | 会话(默认) |
---|---|
BasicHttpBinding | (无) |
WSHttpBinding | 无、可靠会话、(安全会话) |
WSDualHttpBinding | (可靠会话)、安全会话 |
WSFederationHttpBinding | (无)、可靠会话、安全会话 |
NetTcpBinding | (传输)、可靠会话、安全会话 |
NetNamedPipeBinding | 无、(传输) |
NetMsmqBinding | (无)、传输 |
NetPeerTcpBinding | (无) |
MsmqIntegrationBinding | (无) |
BasicHttpContextBinding | (无) |
NetTcpContextBinding | (传输)、可靠会话、安全会话 |
WSHttpContextBinding | 无、可靠会话、(安全会话) |
如果 InstanceContextMode 设置为 PerSession 且 ConcurrencyMode 设置为 Single,则每个代理都获取自己的服务实例。由于一次仅允许一个线程进入服务实例,因此单个代理发出的对服务实例的所有并发调用将顺序排队等候。由于一次仅允许一个线程进入服务实例,因此在该线程退出之前,所有其他调用都将阻塞。如果有大量客户端同时发出调用,这将导致瓶颈。
如果 InstanceContextMode 设置为 PerSession 且 ConcurrencyMode 设置为 Multiple,则每个代理都获取自己的服务实例,且允许并发调用进入服务实例。因此,开发人员必须手动同步对共享数据的所有访问。同样,这会导致对共享数据的访问顺序排队等候,并降低性能,其原因与将 ConcurrencyMode 设置为 Single 时相同。
对于轻型服务实例,Single 和 PerCall 实例上下文模式之间的吞吐量差异不是很大(约为 8%)。
性能数据和测试
用 于收集本文档中讨论的性能数据的计算机配置为:一台服务器和四台客户端计算机,它们通过两个 1 Gbps 以太网网络接口连接。服务器为四处理器的 AMD 64 2.2 GHz 计算机,运行 Windows Server 2008。每台客户端计算机都是双处理器 AMD 2.2GHz x86 计算机,运行的操作系统与服务器相同。系统 CPU 利用率保持在接近 100%。四台客户端计算机用于向 WCF 服务发出调用。向服务发出的每个调用将 1 到 100 个对象传递给服务操作,具体取决于正在执行的测试。每个对象都包含一个订单、有关采购者的信息和要采购的项。
测 试重点是 WCF 技术的服务器吞吐量。这定义为每秒完成的操作数。一个操作是一个请求和答复消息,服务几乎不进行处理。一个要了解的重点是,业务逻辑决定构造良好的 SOA 解决方案中的服务成本。通过省去服务上的业务逻辑处理,仅度量消息传递基础结构的成本。有些测试要求实现服务的类执行某些其他处理。对于这些测试,在服务 类的构造函数中放置了一些逻辑,以生成一组质数。每个测试运行 3 次,然后计算吞吐量的平均值。
下面的代码演示由用于生成性能数据的 WCF 服务实现的接口。
[ServiceContract] public interface ITestContract { [OperationContract] Order[] GetOrders(int NumOrders); } [DataContract] public class OrderLine { [DataMember] public int ItemID; [DataMember] public int Quantity; } [DataContract] public class Order { public Order() { } [DataMember] public int CustomerID; [DataMember] public string ShippingAddress1; [DataMember] public string ShippingAddress2; [DataMember] public string ShippingCity; [DataMember] public string ShippingState; [DataMember] public string ShippingZip; [DataMember] public string ShippingCountry; [DataMember] public string ShipType; [DataMember] public OrderLine[] orderItems; [DataMember] public string CreditCardType; [DataMember] public string CreditCardNumber; [DataMember] public DateTime CreditCardExpiration; [DataMember] public string CreditCardName; } }
下面的代码演示服务的实现。
[ServiceBehavior] public class LightWeightService : ITestContract { static Order[] orders; int upperLimit = 10000; static bool CtorWork = false; public LightWeightService() { if (CtorWork) DoSomething(); } void DoSomething() { List<int> primes = new List<int>(); int j; int last = -1; int lastPrimeSquare = 0; for (int i = 2; i < upperLimit; i++) { for (j = 0; j <= last; j++) { if (i % primes[j] == 0) { break; } } if (j > last) { primes.Add(i); if (i > lastPrimeSquare) { last++; lastPrimeSquare = primes[last] * primes[last]; } } } primes.Clear(); primes = null; } public static void Initialize(int messageSize) { orders = new Order[messageSize]; for (int i = 0; i < messageSize; i++) { Order order = new Order(); OrderLine[] lines = new OrderLine[2]; lines[0] = new OrderLine(); lines[0].ItemID = 1; lines[0].Quantity = 10; lines[1] = new OrderLine(); lines[1].ItemID = 2; lines[1].Quantity = 5; order.orderItems = lines; order.CustomerID = 100; order.ShippingAddress1 = "012345678901234567890123456789"; order.ShippingAddress2 = "012345678901234567890123456789"; order.ShippingCity = "0123456789"; order.ShippingState = "0123456789012345"; order.ShippingZip = "12345-1234"; order.ShippingCountry = "United States"; order.ShipType = "UPS"; order.CreditCardType = "VISA"; order.CreditCardNumber = "0123456789012345"; order.CreditCardExpiration = DateTime.UtcNow; order.CreditCardName = "01234567890123456789"; orders[i] = order; } } public Order[] GetOrders(int NumOrders) { return orders; } }
服务自承载在控制台应用程序中。下面的代码演示如何承载服务。
public static void Main(string[] args) { LightWeightService.Initialize(100); WSHttpBinding binding = new WSHttpBinding(SecurityMode.None, false); ((WSHttpBinding)binding).MaxReceivedMessageSize = 2 * 1024 * 1024; ((WSHttpBinding)binding).ReaderQuotas.MaxArrayLength = 2 * 1024 * 1024; ServiceHost serviceHost = new ServiceHost(typeof(LightWeightService)); ServiceBehaviorAttribute sba = serviceHost.Description.Behaviors.Find<ServiceBehaviorAttribute>(); if (sba == null) { sba = new ServiceBehaviorAttribute(); } sba.ConcurrencyMode = ConcurrencyMode.Single; sba.InstanceContextMode = InstanceContextMode.Single; serviceHost.AddServiceEndpoint(typeof(ITestContract), binding, "http://localhost:8000/PerfTest"); serviceHost.Open(); Console.WriteLine("Service is running..."); Console.WriteLine("Press Enter to terminate service"); Console.ReadLine(); }
客户端应用程序也是一个控制台应用程序。下面的代码演示如何实现客户端。
static void Main(string[] args) { WSHttpBinding binding; ITestContract proxy; ChannelFactory<ITestContract> factory; binding = new WSHttpBinding(SecurityMode.None, false); factory = new ChannelFactory<ITestContract>(binding, new EndpointAddress("http://localhost:8000/PerfTest")); proxy = factory.CreateChannel(); proxy.GetOrders(100); }
文章来自微软MSDN: http://msdn.microsoft.com/zh-cn/library/cc681240.aspx
相关文章推荐
- WCF实例上下文模式与并发模式对性能的影响 转载自:http://log.medcl.net/item/2010/03/wcf-instance-context-mode-and-the-performance-impact-of-conc
- WCF实例上下文模式与并发模式对性能的影响
- (转贴):实例上下文模式和并发模式的性能影响
- ConcurrencyMode.Multiple 模式下的WCF服务就一定是并发执行的吗:探讨同步上下文对并发的影响[下篇]
- 并发与实例上下文模式: WCF服务在不同实例上下文模式下具有怎样的并发表现
- ConcurrencyMode.Multiple模式下的WCF服务就一定是并发执行的吗:探讨同步上下文对并发的影响[上篇]
- WCF并发控制与实例模式
- WCF 学习总结3 -- 实例模式
- WCF并发(Concurrency)的本质:同一个服务实例上下文(InstanceContext)同时处理多个服务调用请求
- WCF 学习总结3 -- 实例模式
- WCF服务实例模式与并发、限流
- WCF实例上下文与并发
- 改进的单例模式,解决并发生成多实例问题,并且提高调用时的性能
- WCF学习--WCF服务实例模式
- WCF并发(Concurrency)的本质:同一个服务实例上下文(InstanceContext)同时处理多个服务调用请求
- WCF 学习总结3 -- 实例模式
- WCF并发(Concurrency)的本质:同一个服务实例上下文(InstanceContext)同时处理多个服务调用请求(转)
- WCF实例上下文以及会话学习
- 【WCF--初入江湖】08 并发与实例模式
- 开启Tomcat APR运行模式,优化并发性能