zoukankan      html  css  js  c++  java
  • 说说WCF中的可信赖会话

    几天前,有朋友在QA上问有关WCF中可信赖会话(ReliableSession)的问题。今天重新梳理一下,主要目就是真正的弄清楚可信赖会话的作用,方法和现实意义。

    正如那位的疑惑一样,很多做过WCF开发的朋友,也都对ReliableSession不太理解。查阅msdn,可以发现ReliableSession是System.ServiceModel命名空间下的一个类。主要的作用如下所述:

    提供对可靠会话绑定元素属性的便捷访问,这些属性是在使用系统提供的绑定之一时提供的。

    包括两个重要的属性(Property)成员:

    1.InActivityTimeout

    文档中的说明是:获取或设置服务在关闭之前保持非活动状态的时间间隔。

    说白了一点呢,就是如果服务停留多长时间没有工作,那我们就关闭他(嘿嘿,有点像公司对待员工一样,偶 尔休息一下子,不干活还行,时间长了,老板会炒你鱿鱼的哦!)

    2.Ordered

    文档中说明为:获取或设置一个值,该值指示消息传递是否必须保持与消息发送一致的顺序。

    任何一方,无论是客户端发送请求消息(Request Message),还是服务端发送相应消息(Response Message)。发送出来的消息都有先后次序,而接收方在接收这些消息的时候,有时候会出现错位的现象,有的消息可能后发先至,而有的可能先发后至,这就影响了通讯双方正常的交互。产生这样现象的主要的原因有两点:

    1)未使用可靠连接协议,使得在传输层中出现类似现象

    2)虽然试用了可靠连接协议,但在发送端或者接收端的通道中(Channel)发送或者接收有顺序问题

    tcp协议用于解决第一个问题,而ReliabelSession的Ordered正可以解决第二个问题。

    在WCF的缺省绑定中,只有以下几种支持或者默认打开了ReliableSession的功能,他们为:

    wsHttpBinding

    wsDualHttpBinding

    wsFederationHttpBinding

    netTcpBinding

    其中netTcpBinding,wsHttpBinding,wsFederationHttpBinding中的ReliableSession属性均是RelibaleSession的一个派生类型,名为OptionRelibaleSession,也就是提供了可选的功能。相比ReliableSession,OptionReliableSession仅仅多了一个属性:Enabled,用这个属性可以指示是否开启可信会话。true代表开启,false的话就不开启了,那么对InActivityTimeout和Ordered的设置将无效。这里面wsHttpBinding和wsFederationHttpBinding其实都继承自wsHttpBindingBase,所在在讨论ReliableSession的时候,这两个Binding表现一致。而对与wsDualHttpBinding则默认的将ReliableSession属性的Ordered设置为了true.也就是说wsDualHttpBinding是缺省支持可信会话的。而ReliableSession的InActivityTimeout默认情况是是10分钟。

    在上面对ReliableSession的描述中,我们可以清楚的看到便捷描述的字样。这是怎么一回事情呢?原来ReliableSession这个class并没有缺省的构造函数,而只是有一个接收ReliableSessionBindingElement类型的构造,这就引出了相比更重要的角色:ReliableSessionBindingElement. 下面就来说说它,并说说它和ReliableSession之间,和Binding之间有着怎样的联系

    ReliableSessionBindingElement:

    BindingElement的一个派生类,也就是说它是一个绑定元素。熟悉WCF架构或者读过大侠Artech<<WCF后续之旅>>的朋友,应该知道WCF的Foundation是如何的。不知道的也没有关系,我也来说说大概,WCF暴露给外界的是终结点(EndPoint),在WCF基础部门,一个终结点又有主要的三部分组成:1)地址 (Address) 2) 绑定Binding  3) 契约 (Contract),也就是传说中的"ABC",呵呵。地址相对比较简单,契约是用于WCF框架留给开发人员创建具体业务逻辑代码的地方,而WCF中,最核心,也是最具有魅力的地方就在于Binding.对于Bind的认识可以帮助我们更清楚的解析WCF的一些特征。一个Binding会维护一个BindElement的集合,这个在Binding的派生类CustomBinding中作为Elements属性来表示,Elements是一个Collection<BindingElement>的类型。在Elements中的每个BindingElement都有着各自的功能,比如在NetTcpBinding中,就存在这这样的一种BindingElement组织方法

    处于第一个位置的是TransactionFlowBindingElement,如果支持ReliableSession的话,那么ReliabelSessionElement就处于NetTcpBinding中的第二个位置 ,如果不支持ReliableSession,则此元素将存在,紧接着的是SecurityBindingElement,随后是BinaryMessageEncodingBindingElement用于消息编码,随后是用于通讯安全的Element,它的类型由NetTcpSecurity属性来决定。最后是TcpTransportBindingElement.而且需要注意的是,每一个Binding中,最后一个Element必须都为TransportBindingElement。在上面的所谈论到的BindingElement中,各自都有各自的功能,他们各司其职,Binding只是将他们紧密的组织在了一起。但每个BindingElement是不是真正的执行者呢?NO!他也是一个组织者,他组织的对象主要有两个:

    ChannelFactory

    ChannelListener

    其中ChannelFactory是作为客户端使用的,而ChannelListener是作为服务端时候使用的。不幸的是,无论是ChannelFactory还是ChannelListener,也都不是真正的执行者,他们是IChannel的工厂类。真正在里面辛勤劳动的还是实现了IChannel的Channel对象。至于说ChannelFactory和ChannelListener是如何组织Channel的,和Channel的一些具体行为,篇幅有限,不再赘述。为了给大家一个详细的认识,画了几幅图:

    image

    接下来,我们分别放大终结点,将终结点的详细构造用图形表达出来:

    image

    BindingElement管理两个对象ChannelFactory和ChannelListener

    这一级的表示图如下:

    image

    上面说了这么多有关WCF基础架构的(Infrastructor)的,下面返回再来看ReliableSessionElement,首先我们就会从宏观上理解它了,它就是一个类型的BindingElement,它包含如下的主要属性成员:

    InActivityTimeout

    Ordered

    MaxRetryCount

    上面的几个重要属性中,InActivityTimeout和Ordered两个属性和ReliabelSession的作用是一致的。而MaxRetryCount用于如果指定了使用可信通道,也就是Ordered为True的时候,当可信通道没有收到消息的时候,通过在基础通道上调用Send方法重发此消息的次数

    ReliabelSession是ReliableSession的一种快捷表示,原因是在构造Binding的时候的,会首先构造一个ReliableSessionElement对象,然后将这个对象的引用传递给ReliableSession对象,这样其实ReliableSession对象其实就是ReliableSessionElement对象中的一部分数据,只是由于暴露ReliabelSessionElement给开发人员,有些不优雅,所以单独设计了这么一个ReliableSession的类,用于快捷表示ReliableSessionElement.

    好了,从理论上讲,我所认识的ReliableSession说的差不多了。下面借鉴一个有趣的实例来检验一下ReliableSession到底有何作用。使用它和不使用它有何异同。

    这个试验的构思来源于WindowsCommunicationFoundation Unleashed<<WCF揭秘>>一书。传说中,这个示例的构思来自于WCF项目经理Shy Cohen.他的思路是将1张图片分成100分,每一份作为一个消息发送给接受者,接受者在根据接收到的消息产生绘制图像。而在发送的过程中,通过插入一个自定义的BinddingElement,将数据分概率的截取下来不予发送。这时候,如果不采用ReliableSession,那么接收方收到的图像是不完整的。有一小部分缺失,而如果采用了ReliableSession呢,那尽管发送的时候,在被拦截的时候的当此发送中,消息的确没有发出去,但基础通道会尝试进行重发,重发的包有很小几率会再次被拦截,如果再次被拦截,那么会再次重发,那么被拦截的几率会更小,这时候接受者收到的是完整的图像。

    在Shy Cohen的试验中,由三个组件构成:

    发送者(Sender)

    接受者 (Receiver)

    对照者 (Router)

    他们之间的关系如图:

    image

    对照者能够指定发送者漏包的比率,比如1%,10%等,发送者与对照者之间一直使用的是没有可靠连接的会话,试验的步骤是:

    1)首先将接受者和发送者都设置为不接受可信赖会话。设置的方法就是将各自config中的添加<reliableSession Ordered="false"/>。此时,运行三个程序,在对照者中调整丢包频率,在发送者中选择一幅图片,注意:最好是它例子中给定的Seattle.jpg,因为其他图片可能因为过大,而造成异常。选择图片之后,点击发送。此时,在对照者和接受者中会显示出接收到的包数目,丢失的数目,和发送的数目。如果设置的比率比较大的话,会发现接受者所形成的图像有明显缺失。对照者中的丢包数目也大于0

    通过这一步骤,可以得出结论,如果没有采用可信会话,消息在发送的过程中是有可能丢失或者错位的,尽管我们使用的是Tcp协议

    2)将接受者和发送者config中的配置更改为<reliableSession Ordered="true"/>,此时,再次选择图片,发送,会发现在偶尔的几次中,发送操作进行的非常迟钝,但发送完成之后,接受者的图像是完整的,而对照者仍然存在着一些丢失的消息。

    通过这个试验,能清晰的表达可信会话的功能和意义。我这里这是做了一个介绍,更多更详细的请阅读<<WCF揭秘>>第四章。

    作者:jillzhang
    出处:http://jillzhang.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Linux常用命令-centos
    USACO 2006 Open, Problem. The Country Fair 动态规划
    USACO 2007 March Contest, Silver Problem 1. Cow Traffic
    USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法
    USACO 2015 February Contest, Silver Problem 3. Superbull Prim最小生成树算法
    LG-P2804 神秘数字/LG-P1196 火柴排队 归并排序, 逆序对
    数据结构 并查集
    浴谷国庆集训 对拍
    1999 NOIP 回文数
    2010 NOIP 普及组 第3题 导弹拦截
  • 原文地址:https://www.cnblogs.com/jillzhang/p/1313675.html
Copyright © 2011-2022 走看看