WCF 4.0一个鲜为人知的改变[兼书名征集]

本篇文章介绍可以算是WCF 4.0基于限流(Throttling)的新特性,是在修订《WCF技术剖析(卷1)》的时候编写演示实例的时候发现的。这个特性没有出现在官方文档上面,至少在MSDN上的相关介绍依然是错误的。

一、流量限制简介

WCF是一个基于多线程的消息监听、接收和处理框架体系,能够同时应付来自相同或者不同客户端的服务调用请求,并提供完善的同步机制确保状态的一致性。一方面,我们期望WCF服务端能够处理尽可能多的并发请求,但是资源的有限性决定了并发量有一个最大值。如果WCF不控制进入消息处理系统的并发量,试图处理所有抵达的并发请求,一旦超过了这个临界值,整个服务端将会由于资源耗尽而崩溃。

所以,我们需要在WCF的消息接收系统和消息处理系统之间设置一道道屏障,将流入消息处理系统的请求控制到一个最佳的范围,以实现对现有资源的有效利用,从而达到确保服务的可用性和提高整体吞吐量的目的。WCF的流向限制(Throttling)为你设置了这些屏障,你可以根据现有的软硬件环境对该闸门准入的并发流量进行动态的配置。

WCF对限流的控制是通过一个服务行为(Service Behavior)实现的,该服务行为类型名称为ServiceThrottlingBehavior,定义在System.ServiceModel.Description命名空间下。ServiceThrottlingBehavior定了三个整型的属性:MaxConcurrentCallsMaxConcurrentInstancesMaxConcurrentSessions。它们分别代表流量控制的三个阀值,简单地说,我们所说的限流就是通过设置这三个值控制能够处理的并发量。

二、MSDN关于三个限流阀值的介绍

基于.NET Framework 4.0的MSDN对上述三个限流阀值是这样介绍的:

三、通过实例测试默认的最大并发会话数

通过ServiceThrottlingBehaviorMaxConcurrentSessions属性表示的最大并发会话数默认为10,果真如此吗?我们不妨通过一个简单的实例来验证。照理以计算服务为例,下面是契约接口和服务类型的定义。

   1: [ServiceContract(Namespace ="http://www.artech.com/")]
   2: public interface ICalculator
   3: {
   4:     [OperationContract]
   5:     double Add(double x, double y);
   6: }
   7:  
   8: public class CalculatorService : ICalculator
   9: {      
  10:     public double Add(double x, double y)
  11:     {
  12:         return x + y;
  13:     }
  14: }

我们采用控制台程序对CalculatorService进行寄宿,如下所示的是采用的配置:

   1: <configuration>
   2:   <system.serviceModel>
   3:     <services>
   4:       <service name="Artech.WcfServices.Service.CalculatorService">
   5:         <endpoint  address="http://127.0.0.1:3721/calculatorservice"
   6:                    binding="ws2007HttpBinding"
   7:                    contract="Artech.WcfServices.Service.Interface.ICalculator"/>
   8:       </service>
   9:     </services>
  10:   </system.serviceModel>
  11: </configuration>

从上面的配置中我们知道寄宿的服务具有一个唯一的基于WS2007HttpBinding(支持会话)的终结点。客户端采用相应的配置并通过如下的代码进行服务的调用。

   1: using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorservice"))
   2: {
   3:     bool stop = false;
   4:     for (int i = 0; i < 1000 && !stop; i++)
   5:     {
   6:         ICalculator calcultor = channelFactory.CreateChannel();
   7:         try
   8:         {
   9:             calcultor.Add(1, 2);
  10:             Console.WriteLine("第{0}个服务代理调用成功!", i + 1);
  11:         }
  12:         catch (Exception ex)
  13:         {
  14:             Console.WriteLine("出现异常:{0}", ex.Message);
  15:             stop = true;
  16:         }
  17:     }
  18:    }

在上面这段用于进行服务调用的代码中,我们通过基于客户端终结点配置名称创建的ChannelFactory<TChannel>对象创建了1000个服务代理进行用其进行1000次服务调用。当上面这个实例运行的时候,客户端控制台将会出现如下的输出结果。实例程序清晰地反映了这样的事实:虽然我们通过不同的服务代理对象进行了1000次服务调用,但是只有前面两百次是成功的。如果默认的最大并发会话数是10的话,只有前面10次服务调用会成功。

   1: 第1个服务代理调用成功!
   2: 第2个服务代理调用成功!
   3:    ...
   4: 第199个服务代理调用成功!
   5: 第200个服务代理调用成功!
   6: 出现异常:请求通道在等待 00:00:59.9844000 以后答复时超时。增加传递给请求调用的超时值,或者增加绑定上的 SendTimeout 值。分配给此操作的时间可能已经是更长超时的一部分。

四、WCF 4.0中三个限流默认阀值具体是多少呢?

通过上面演示的实例,我们发现默认情况下允许200次并发会话,那么MaxConcurrentSessions的默认值不是10,而是200吗?由于三个限流属性值是通过配置的方式进行指定的,所以要了解它们的默认值,只需要了解对应的配置元素类型的定义即可。下面是ServiceThrottlingBehavior对应的配置元素ServiceThrottlingElement 的定义。

   1: public sealed class ServiceThrottlingElement : BehaviorExtensionElement
   2: {
   3:      //...
   4:     [ConfigurationProperty("maxConcurrentCalls", DefaultValue=0x10)]
   5:     public int MaxConcurrentCalls { get; set; }
   6:  
   7:     [ConfigurationProperty("maxConcurrentInstances", DefaultValue=0x74)]
   8:     public int MaxConcurrentInstances { get; set; }
   9:  
  10:     [ConfigurationProperty("maxConcurrentSessions", DefaultValue=100)]
  11:     public int MaxConcurrentSessions { get; set; }
  12: }
  13:  

从应用在三个配置属性上ConfigurationPropertyAttribute特性可以看出,MaxConcurrentCalls、MaxConcurrentInstances
和MaxConcurrentSessions 的默认值为16、116和100,而不是MSDN所说的16、26和10。

既然MaxConcurrentSessions的默认值为100,那么我们的实例为什么会有200次成功的并发访问呢?原因很简单:这三个限流阀值都是针对单个处理器的,由于运行机器采用双核处理器,自然就是200。



[书名征集] 前后花了一年多的时间,终于将《WCF技术剖析(卷2)》完成了,不过在对《卷1》进行修订的时候又对现有的内容作了较大的改动。这不仅仅添加了许多新的内容,还大刀阔斧的删除和修改了现有的一些内容。正是由于改动较大,编辑建议换个名字并出上下卷。由于我个人还未给新书想到一个好的名字,希望通过本贴进行征名。你提供的书名一旦采用,在新书出版时我个人会赠送本书的上下两册。

[上册目录]

[下册目录]

作者:蒋金楠
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文链接

时间: 2025-01-01 14:33:55

WCF 4.0一个鲜为人知的改变[兼书名征集]的相关文章

[WCF 4.0新特性] 默认终结点

很多WCF的初学者是从之前的Web服务上转移过来的,他们非常怀念.asmx Web服务无配置的服务寄宿方式.你只需要在定义Web服务的时候再表示服务操作的方法上应用WebMethodAttribute特性就可以了,完全可以不需要手工进行相应的配置,因为Web服务运行时会自动为你添加默认的配置.但是对于WCF来说,在进行服务寄宿的时候,你必须以编程或者配置的方式为服务添加至少一个终结点,而终结点需要具备基本的ABC三要素. 对于最新版本的WCF编程人员来说,你也可以采用无配置的服务寄宿了,这主要得

mfc-C++6.0一个关于static的小问题

问题描述 C++6.0一个关于static的小问题 static可以通过拖动来滚动上面的绘图么?重新绘图的定位是怎么样的,MFC 解决方案 scrollviewhttp://blog.csdn.net/scyatcs/article/details/7942585 解决方案二: 可以,但是需要给static手动的绑定一个滚动条才可以,重绘的本质就刷新界面的同时,改变绘图的点坐标,定位的话可以根据滚动条当前位置对绘图的坐标进行一个计算和显示 解决方案三: 省事儿点的方式是直接在单文档程序中绘图,这

[WCF 4.0新特性] 路由服务[实例篇]

在本篇文章中,我们将通过一个具体的实例来演示如何通过路由服务.在这个例子中,我们会创建连个简单的服务HelloServie和GoodbyeService.假设客户端不能直接调用这两个服务,需要使用到路由服务作为两者之间的中介.整个消息路由的场景如下图所示,中间的GreetingService.svc就是代表路由服务,而两个目标服务则通过HelloServie.svc和GoodbyeService.svc表示.路由服务使用的消息筛选器EndpointAddressMessageFilter,即根据

[WCF 4.0新特性] 标准终结点与无(.SVC)文件服务激活

今天介绍WCF 4.0的另外两个新特性:标准终结点(Standard Endpoint)和无(.SVC)文件服务激活(File-Less Activation).前者实现了针对典型通信场景对终结点的定制,后者让你在进行IIS/WAS的服务寄宿中无须定义.svc文件. 一.标准终结点 我们知道,绑定的本质就是一系列相关绑定元素的有序集合,而系统绑定就是基于若干典型的通信场景对相关绑定元素的整合.WCF通过系统绑定对绑定元素进行了定制,那么能否在终结点级别对组成该终结点的ABC(地址.绑定和契约)也

[WCF 4.0新特性] 路由服务[原理篇]

在一个典型的服务调用场景中,具有两个基本的角色,即服务的消费者和服务的提供者.从消息交换的角度讲前者一般是消息的最初发送者,而后者则是消息的最终接收者.在很多情况下,由于网络环境的局限,消息的最初发送者和最终接收者不能直接进行消息交换,这就需要一个辅助实现消息路由的中介服务,这就是我们接下来要介绍的路由服务. 目录 一.路由服务就是一个WCF服务       路由服务契约的定义       路由服务契约的定义 二.基于消息内容的路由策略       RoutingBehavior服务行为    

[WCF 4.0新特性] 默认绑定和行为配置

对于传统的WCF配置系统,无论是绑定的配置还是行为(服务行为和终结点行为)都必须具有一个名称.而正是通过整个配置名称,它们才能被应用到目标对象(终结点或者服务)上.而在实际的项目开发中,绝大部分服务或者终结点都具有相同的绑定和行为,如果能够定义一种默认的绑定和行为,这无疑会简化我们的配置.WCF4.0为此提供了一个新的特性以支持默认绑定和行为的配置. 一. 默认绑定配置 在传统的配置方式下,如果我们需要对终结点的绑定(不论是系统绑定还是自定义绑定)进行定制,我们都需要配置一个"具名"的

状态同步-如果同步一个状态经常改变的设备

问题描述 如果同步一个状态经常改变的设备 本人有两个设备,一个是主设备,另一个是冗余设备,设备靠IP网络对外提供服务,客户会经常操作这个设备,也就是设备的状态会经常的改变,并且设备的状态还很多,请问各位大神,有没有什么相对较好的办法,使冗余设备与主设备的状态能够较好的同步吗? 我原本想将所有的状态保存下来,但是由于状态经常改变,频繁的IO操作肯定会影响性能. 解决方案 试试zookeeper

java点击一个按钮怎么改变另一个窗口标签内容

问题描述 java点击一个按钮怎么改变另一个窗口标签内容 这是类A的按钮JButton pingguo = new JButton(""苹果""); pingguo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new FrameP(); } }); pingguo.setForeground(new Color(255 99 71)); p

vb6.0-VB6.0 一个关于Type字符串分配的问题

问题描述 VB6.0 一个关于Type字符串分配的问题 Visula Basic 6.0调用c++,一个结构体的分配,里面有一个bstr类型的字符串,怎么拿值呢? 解决方案 http://blog.csdn.net/zeuskaaba/article/details/4082826 解决方案二: vb6.0 中 事务处理的一个问题