控制并发访问的三道屏障: WCF限流(Throttling)体系探秘[上篇]
WCF是一个基于多线程的消息监听、接收和处理框架体系,能够同时应付来自相同或者不同客户端的服务调用请求,并提供完善的同步机制确保状态的一致性。一方面,我们期望WCF服务端能够处理尽可能多的并发请求,但是资源的有限性决定了并发量有一个最大值。如果WCF不控制进入消息处理系统的并发量,试图处理所有抵达的并发请求,一旦超过了这个临界值,整个服务端将会由于资源耗尽而崩溃。
所以,我们需要在WCF的消息接收系统和消息处理系统之间设置一道道屏障,将流入消息处理系统的请求控制到一个最佳的范围,以实现对现有资源的有效利用,从而达到确保服务的可用性和提高整体吞吐量的目的。WCF的流向限制(Throttling)为你设置了这些屏障,你可以根据现有的软硬件环境对该闸门准入的并发流量进行动态的配置。我们先来看看如何进行限流控制。
一、如何进行限流控制
WCF对限流的控制是通过一个服务行为(Service Behavior)实现的,该服务行为类型名称为ServiceThrottlingBehavior,定义在System.ServiceModel.Description命名空间下。我们先来看看ServiceThrottlingBehavior的定义:
1: public class ServiceThrottlingBehavior : IServiceBehavior
2: {
3: public ServiceThrottlingBehavior();
4: void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters);
5: void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase);
6: void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase);
7:
8: public int MaxConcurrentCalls { get; set; }
9: public int MaxConcurrentInstances { get; set; }
10: public int MaxConcurrentSessions { get; set; }
11: }
从上面的代码中我们可以看到,ServiceThrottlingBehavior定了三个整型的属性:MaxConcurrentCalls、MaxConcurrentInstances和MaxConcurrentSessions。它们分别代表流量控制的三个阀值,简单地说,我们所说的限流就是通过设置这三个值控制能够处理的并发量。这三个属性所代表的数值是针对某个ServiceHost而言的。接下来,我们来简单地说说这个阀值具体代表什么含义:
- MaxConcurrentCalls:当前ServiceHost能够处理的最大并发消息数量,默认值为16;
- MaxConcurrentInstances:当前ServiceHost允许存在的InstanceContext的最大数量,默认值为26;
- MaxConcurrentSessions:当前ServiceHost允许的最大并发会话数量,默认值为10。
由于控制流量的ServiceThrottlingBehavior是一个服务行为,我们可以通过编程和配置的方式对上述的三个允许的最大并发值进行设置。
二、通过编程的方式设置最大并发值
由于控制流量的ServiceThrottlingBehavior是一个服务行为,我们在进行服务寄宿(自我寄宿)的时候,直接通过编程的方式将该服务行为添加到服务描述的行为列表之中。在下面的服务寄宿代码中,我们将CalculatorService服务的MaxConcurrentCalls、MaxConcurrentSessions和MaxConcurrentInstances分别设置成50、30和20。需要注意的是,所有的设置必须在开启ServiceHost(调用Open方法)之前完成方能生效。在ServiceHost开启的状态下的什么限流设置均是无效的,至于具体的原因,可以参考《WCF技术剖析(卷1)》第7章关于服务描述和服务寄宿过程相关内容。
1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
2: {
3: ServiceThrottlingBehavior throttlingBehavior = host.Description.Behaviors.Find<ServiceThrottlingBehavior>();
4: if (null == throttlingBehavior)
5: {
6: throttlingBehavior = new ServiceThrottlingBehavior();
7: host.Description.Behaviors.Add(throttlingBehavior);
8: }
9:
10: throttlingBehavior.MaxConcurrentCalls = 50;
11: throttlingBehavior.MaxConcurrentInstances = 30;
12: throttlingBehavior.MaxConcurrentSessions = 20;
13:
14: host.Open();
15: Console.Read();
16: }
不过我们很少通过编程的方式进行限流的控制,更多地,还是采用配置的方式。
三、通过配置的方式设置最大并发量
基本上所有服务行为均可用通过配置的方式应用到相应的服务上面,上述的关于限流的三个最大并发量通常都是采用配置的方式进行设置的。对于系统定义的服务行为来说,WCF均会为其定义相应的配置元素。同理,如果我们希望通过配置的方式应用自定义的服务行为,我们也需要定义相应的配置元素。ServiceThrottlingBehavior的配置元素定义在ServiceThrottlingElement类型中,在具体介绍限流配置之前,我们不妨先来看看ServiceThrottlingElement的定义:
1: public sealed class ServiceThrottlingElement : BehaviorExtensionElement
2: {
3: //其他成员
4: [ConfigurationProperty("maxConcurrentCalls", DefaultValue = 16)]
5: public int MaxConcurrentCalls { get; set; }
6:
7: [ConfigurationProperty("maxConcurrentInstances", DefaultValue = 26)]
8: public int MaxConcurrentInstances { get; set; }
9:
10: [ConfigurationProperty("maxConcurrentSessions", DefaultValue = 10)]
11: public int MaxConcurrentSessions { get; set; }
12: }
ServiceThrottlingElement的定义暴露了ServiceThrottlingBehavior对应配置项的结构。实际上,整个配置项由单纯的三个配置属性构成,它们分别代表上述的三的最大并发值。此外,ServiceThrottlingElement还透露给我们 一个重要的信息,就是这三个最大并发量的默认值。MaxConcurrentCalls、MaxConcurrentInstances和MaxConcurrentSessions在默认的情况下的值为16、26和10,这和上面的介绍是一致的。
如果通过配置的方式控制限流,我们只需要将ServiceThrottlingBehavior对应的配置,即通过ServiceThrottlingElement定义的配置元素定义在相应的服务行为配置中即可,相应配置项的名称为serviceThrottling。通过下面的配置,我将CalculatorService的三个最大并发量(MaxConcurrentCalls、MaxConcurrentInstances和MaxConcurrentSessions)分别设置为50、30和20。
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <system.serviceModel>
4: <behaviors>
5: <serviceBehaviors>
6: <behavior name="throttlingBehavior">
7: <serviceThrottling maxConcurrentCalls="50" maxConcurrentInstances="30" maxConcurrentSessions="20" />
8: </behavior>
9: </serviceBehaviors>
10: </behaviors>
11: <services>
12: <service behaviorConfiguration="throttlingBehavior" name="Artech.ConcurrentServiceInvocation.Service.CalculatorService">
13: <endpoint address="http://127.0.0.1:8888/calculatorservice" binding="basicHttpBinding" contract="Artech.ConcurrentServiceInvocation.Service.Interface.ICalculator" />
14: </service>
15: </services>
16: </system.serviceModel>
17: </configuration>
通过上面介绍,我们知道了如何通过编程和配置的方式设置相应的最大并发量,从而指导WCF的限流体系按照你设定的值对并发的服务调用请求进行限流控制。那么,在WCF框架体系内部,整个过程是如何实现的呢?请听下回分解。
- Android中的FragmentManager的问题
- Premiere Pro & After Effects插件开发调试方法
- RegQueryValueEx正确使用方法
- 区块链+医疗五类应用前景广阔,英美已有企业试水
- Linux进程关系
- 基于OBS的插件开发总结
- Linux从程序到进程
- asp.net 解码gb2312下urlencode后的字符串
- XCode日常使用备忘录
- .net中close和dispose及关闭流操作
- Linux文件管理相关命令
- 实现滑动分页(微博分页方式)
- 腾讯汇赢正式上线,变革2018大连房地产市场营销
- Windows下程序启动时出现0xc000007b错误的解决方案
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 算法篇:树之翻转树
- 每日一题 | 约瑟夫问题
- 编码的浪漫:完美序列化的官方评测
- 【Vulnhub】symfonos2
- PWN入门(unsafe unlink)
- tf_cnn_benchmark 显存问题
- Spark on Kubernetes PodTemplate 的配置
- IO ports
- 【android系统】使用s3来上传下载文件
- 【Spark on Kubernetes】Executor环境变量
- Python获取字典值
- 应用程序InetlliJ IDEA不能打开
- yum install空间不足
- prometheus-nginxlog-exporter构建Nginx日志监控
- s3cmd put文件的过程