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。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Jack-Cui

Jetson TX1开发笔记(三):开发利器-Nsight Eclipse Edition

PC平台(Host): 虚拟机Ubuntu14.04 嵌入式平台(Target): Jeston TX1 一、NSight简介     Jetpack开...

31550
来自专栏PHP在线

Web开发常见的几个漏洞解决方法

平时工作,多数是开发Web项目,由于一般是开发内部使用的业务系统,所以对于安全性一般不是看的很重,基本上由于是内网系统,一般也很少会受到攻 击,但有时候一些系统...

482110
来自专栏Debian社区

协议介绍之深入了解 gRPC

经过很长一段时间的开发,TiDB 终于发了 RC3。RC3 版本对于 TiKV 来说最重要的功能就是支持了 gRPC,也就意味着后面大家可以非常方便的使用自己喜...

37940
来自专栏开发 & 算法杂谈

并行化的动态数据竞争验证和检测方法

之前系列提到的动态数据竞争验证和检测方法是结合了验证和检测两部分。这篇文章主要介绍一下并行化的动态数据竞争验证和检测方法。

23840
来自专栏张善友的专栏

[腾讯社区开放平台]介绍开放授权协议-OAuth

OAuth (开放授权) 是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所...

28070
来自专栏信安之路

新手指南:Bwapp之XSS –stored

XSS 全称:跨站脚本( Cross Site Scripting ),为了不和层叠样式表( Cascading Style Sheets )的缩写 CSS 混...

12700
来自专栏Golang语言社区

设计Go API的管道使用原则

管道是并发安全的队列,用于在Go的轻量级线程(Go协程)之间安全地传递消息。总的来讲,这些原语是Go语言中最为称道的特色功能之一。这种消息传递范式使得开发者可以...

37560
来自专栏散尽浮华

MongoDB集群运维笔记

前面的文章介绍了MongoDB副本集和分片集群的做法,下面对MongoDB集群的日常维护操作进行小总结:         MongDB副本集故障转移功能得益于它...

2K90
来自专栏Kirito的技术分享

浅析项目中的并发(二)

分布式遭遇并发 在前面的章节,并发操作要么发生在单个应用内,一般使用基于JVM的lock解决并发问题,要么发生在数据库,可以考虑使用数据库层面的锁,而在分布式...

404130
来自专栏北京马哥教育

一万两千字长文,六大问题为你解读计算机

1描述计算机的组成及其功能 电子计算机,亦称电脑,是一种利用电子学原理,根据一系列指令对数据进行处理的工具 计算机及其组成 计算机是什么       电子计...

388100

扫码关注云+社区

领取腾讯云代金券