WCF技术剖析之九:服务代理不能得到及时关闭会有什么后果?
原文:WCF技术剖析之九:服务代理不能得到及时关闭会有什么后果?
我们想对WCF具有一定了解的人都会知道:在客户端通过服务调用进行服务调用过程中,服务代理应该及时关闭。但是如果服务的代理不等得到及时的关闭,到底具有怎样的后果?什么要关闭服务代理?在任何时候都需要关闭服务代理吗?是否有一些例外呢?本篇文章将会围绕着这些问题展开。
一、会话信道(Sessionful Channel) V.S. 数据报信道(Datagram Channel)
WCF通过信道栈实现了消息的编码、传输及基于某些特殊功能对消息的特殊处理,而绑定对象是信道栈的缔造者,不同的绑定类型创建出来的信道栈具有不同的特性。就对会话的支持来讲,我们可以将信道分为以下两种:
- 会话信道(Sessionful Channel):会话信道确保客户端和服务端之间传输的消息能够相互关联,但是信道的错误(Fault)会影响后续的消息交换;
- 数据报信道(Datagram Channel):即使在同一个数据报信道中,每次消息的交换都是相互独立,信道的错误也不会影响后续的消息交换。
对于绝大部分绑定类型(BasicHttpBinding除外),在默认的情况下创建的都是会话信道。对于WCF客户端来说,如果进行基于会话信道的服务调用,有一些问题需要引起足够的重视,如果使用不当,不但影响客户端本身的服务调用,还会对服务处理请求的吞吐量造成很大的影响。
二、服务代理的关闭与并发会话(Concurrent Sessions)的限制
基于会话信道服务调用须要注意的第一个问题和WCF流量限制有关,为了使读者对这个问题先有一个直观认识,我们照例通过一个简单的实验来重现须要解决的问题。本例使用我们熟悉的计算服务例子,在服务寄宿的时候采用WsHttpBinding,下面是客户端程序。
1: Binding binding = new WsHttpBinding(); EndpointAddress address = new EndpointAddress("http://127.0.0.1:9999/calculateservice"); ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(binding, address); for (int i = 1; i <= 20; i++)
2: {
3: try
4: {
5: ICalculator calculator = channelFactory.CreateChannel();
6: Console.WriteLine("{3}: x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2), i);
7: }
8: catch (Exception ex) { Console.WriteLine("{0}t: {1}", i, ex.Message); }
9: }
输出结果:
1: 1 : x + y = 3 when x = 1 and y = 2
2: 2 : x + y = 3 when x = 1 and y = 2
3: ......
4: 10: x + y = 3 when x = 1 and y = 2
5: 11: x + y = 3 when x = 1 and y = 212:请求通道在等待 00:00:59.9840000以后答复超时。增加传递给请求调用的超时值,或者增加绑定上的 SendTimeout 值。分配给此操作的时间可能是更长超时的一部分
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
从输出的结果可以看出,虽然在代码中我们通过一个for循环进行了20次服务调用,但是真正成功执行的仅仅有11次,第12次进行服务调用的时候,抛出Timeout异常。这种情况的出现源于WCF对并发会话数量的控制。说得具体点,WCF对一个ServiceHost所能处理的并发会话作了限制,在默认的情况下,允许的最大并发会话数量为10。
那么细心的读者马上会问一个问题,既然默认的并发会话数量为10,为什么上面的例子中,会有11次成功的并发服务调用呢?这是因为,服务端的信道监听器允许一个额外的会话信道。在很多情况下,11个并发会话肯定是不能满足具体的需求的,那么是否可通过相应的配置根据具体的需求灵活指定一个合适的最大并发会话数量呢?答案是肯定的,服务允许的最大并发会话可以通过ServiceThrottlingBehavior服务行为的MaxConcurrentSessions属性进行配置。在下面的配置中,将该值设为了20。
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <system.serviceModel>
4: <behaviors>
5: <serviceBehaviors>
6: <behavior name="highConcurrencyBehavior">
7: <serviceThrottling maxConcurrentSessions="20" />
8: </behavior>
9: </serviceBehaviors>
10: </behaviors>
11: ... ...
12: </system.serviceModel>
13: </configuration>
WCF对服务的并发会话的限制给WCF客户端提出了一个要求,那就是在服务代理不再使用的情况下,应该及时将其关闭。基于服务代理对象的会话会随着服务代理的关闭而关闭。服务端在处理客户端请求的时候,如果当前并发的会话数量超过了所允许的范围,后续的请求将会被放入等待队列,以等待现有会话的结束。对于客户端来说,服务调用在允许的超时时限(默认1分钟)内还未接收到回复,则会抛出一个TimeoutException异常,如例子所表现的一样。如果能够及时地关闭服务代理对象,即使是2000次调用都没有问题,如下所示:
1: Binding binding = new WSHttpBinding();
2: EndpointAddress address = new EndpointAddress("http://127.0.0.1:9999/calculateservice");
3: ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(binding, address);
4: for (int i = 1; i <= 2000; i++)
5: {
6: ICalculator calculator = channelFactory.CreateChannel();
7: Console.WriteLine("{3}: x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2), i);
8: (calculator as ICommunicationObject).Close();
9: }
输出结果:
1: 1 : x + y = 3 when x = 1 and y = 2
2: 2 : x + y = 3 when x = 1 and y = 2
3: ......
4: 1999: x + y = 3 when x = 1 and y = 2
5: 2000: x + y = 3 when x = 1 and y = 2
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
三、服务代理的关闭与否对数据报信道没有影响
上面讲的是对最大会话的限制,实际也可以说成是对最大会话信道的限制,那么对于非会话信道是否也有此限制呢?实践出真知,照例通过具体的例子来说明问题。我们知道绑定是信道的创建者,信道的特性通过组成绑定的元素(绑定元素)决定,所以信道对会话支持的特性也不例外。以上面例子使用的WsHttpBinding为例,只有WsHttpBinding的安全(Security)或可靠会话(Reliable Session)开启的情况下,创建的信道才具有会话的特性,否则创建出来的信道是不能支持信道的。在默认的情况下,WsHttpBinding的安全模式(SecurityMode)为基于消息的安全,所以创建出来的信道自动被赋予了会话的特性。
为了验证在非会话信道的情况下,WCF最大并发会话限制是否存在,我们对上面的代码稍加修改,在创建WsHttpBinding的时候,将安全模式设为SecurityMode.None(当然,在进行服务寄宿的时候,WsHttpBinding也须要进行相同的设置)。通过最终输出结果可以看出,MaxConcurrentSessions的限制不适合非会话邦定。
1: Binding binding = new WSHttpBinding(SecurityMode.None);
2: EndpointAddress address = new EndpointAddress("http://127.0.0.1:9999/calculateservice");
3: ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(binding, address);
4: for (int i = 1; i <= 2000; i++)
5: {
6: ICalculator calculator = channelFactory.CreateChannel();
7: Console.WriteLine("{3}: x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2), i);
8: }
输出结果:
1: 1 : x + y = 3 when x = 1 and y = 2
2: 2 : x + y = 3 when x = 1 and y = 2
3: ......
4: 1999: x + y = 3 when x = 1 and y = 2
5: 2000: x + y = 3 when x = 1 and y = 2
出处:http://artech.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
WCF技术剖析之九:服务代理不能得到及时关闭会有什么后果?的更多相关文章
- WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用
原文:WCF技术剖析之十五:数据契约代理(DataContractSurrogate)在序列化中的作用 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经> ...
- WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理
原文:WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理 在前面一片文章(服务代理不能得到及时关闭会有什么后果?)中,我们谈到及时关闭服务代理(Service Proxy)在一个高并发环境 ...
- WCF技术剖析之十四:泛型数据契约和集合数据契约(下篇)
原文:WCF技术剖析之十四:泛型数据契约和集合数据契约(下篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]在.NE ...
- WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制
原文:WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制 和传统的分布式远程调用一样,WCF的服务调用借助于服务代理(Service ...
- WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成
原文:WCF技术剖析之七:如何实现WCF与EnterLib PIAB.Unity之间的集成 在这之前,我写过深入介绍MS EnterLib PIAB的文章(参阅<MS Enterprise Li ...
- WCF技术剖析之三十:一个很有用的WCF调用编程技巧[下篇]
原文:WCF技术剖析之三十:一个很有用的WCF调用编程技巧[下篇] 在<上篇>中,我通过使用Delegate的方式解决了服务调用过程中的异常处理以及对服务代理的关闭.对于<WCF技术 ...
- WCF技术剖析之三十:一个很有用的WCF调用编程技巧[上篇]
原文:WCF技术剖析之三十:一个很有用的WCF调用编程技巧[上篇] 在进行基于会话信道的WCF服务调用中,由于受到并发信道数量的限制,我们需要及时的关闭信道:当遇到某些异常,我们需要强行中止(Abor ...
- 《WCF技术剖析》博文系列汇总[持续更新中]
原文:<WCF技术剖析>博文系列汇总[持续更新中] 近半年以来,一直忙于我的第一本WCF专著<WCF技术剖析(卷1)>的写作,一直无暇管理自己的Blog.在<WCF技术剖 ...
- WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]
原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码 ...
随机推荐
- Qt学习 之 数据库(支持10种数据库)
Qt 提供了 QtSql 模块来提供平台独立的基于 SQL 的数据库操作.这里我们所说的“平台独立”,既包括操作系统平台,有包括各个数据库平台.另外,我们强调了“基于 SQL”,因为 NoSQL 数据 ...
- js 选择器
a>b 获取a下面的直接子元素
- python pythonic是什么?
原文地址:http://faassen.n--tree.net/blog/view/weblog/2005/08/06/0 注:Martijn 是 Zope 领域的专家,他为 Zope 系列产品做了许 ...
- poj 2245 Lotto(dfs)
题目链接:http://poj.org/problem?id=2245 思路分析:无重复元素组合组合问题,使用暴力枚举法,注意剪枝条件. 代码如下: #include <iostream> ...
- iOS KVO & KVC
键值观察:值更改时通知观察者 键值观察(Key-value observing,或简称 KVO)允许对象观察另一个对象的属性.该属性值改变时,会通知观察对象.它了解新值以及旧值:如果观察的属性为对多的 ...
- C语言中操作符的优先级大全
C语言中操作符的优先级大全, 当然c++, Objective-C,大部分语言都试用. 下面是来自The C Programming Language 2th的总结. OperatorsAssocia ...
- Cocos2d-x 创建自己定义项目模板
你是否以前为cocos方便高速开发而兴奋,你是否以前为各种工具的便利开发而感动,但如今的你是否为每次创建一个新的项目都是HelloWorldScene而苦恼? 好吧,事实上我也感觉到了,每次创建一个项 ...
- 关于jave在oracle驱动下事务提交与回滚问题
一直以来,都觉得Connection假设设置了setAutoCommit(false)后.启动手工事务提交.必须手工进行commit或者rollback才行.今天正好遇到一个问题.结果大跌眼镜. 于是 ...
- 【Hibernate】HQL new map
HQL 查询如果需要带出对象(比如:OneToOne子对象)的一两个属性,而不是全部带出.可以使用 select new map的方法带出. 1.lazy还是设置为false /**关联属性对象*/ ...
- java实现文件夹(包括其中的子文件夹、子文件)的复制——递归
这是学校java课的一道实验题,题目如下:编程,根据指定的源和目标位置,完成指定文件或文件夹(包括其中的子文件夹.子文件)的复制. 以下是我的实现,使用了递归: package com.simon.m ...