首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

可靠性

WCF与其他面向服务技术之间最大的区别在于传输可靠性(Transport Reliability)与消息可靠性(Message Reliability)。传输可靠性(例如通过TCP传输)在网络数据包层提供了点对点保证传递(Point-to-Point Guaranteed Delivery),以确保数据包的顺序无误。传输可靠性不会受到网络连接的中断或其他通信问题的影响。

顾名思义,消息可靠性负责处理消息层的可靠性,它与传递消息的数据包数量无关。消息可靠性提供了端对端保证传递(End-to-End Guaranteed Delivery),确保消息的顺序无误。消息可靠性与引入的中间方的数量无关,与网络跳数(Network Hops)的数量也没有关联。消息可靠性基于一个行业标准。该行业标准为可靠的基于消息的通信维持了一个在传输层的会话。如果传输失败,例如无线连接中断,消息可靠性就会提供重试(Retries)功能。它还能够自动处理网络阻塞(Congestion)、消息缓存(Message Buffering)以及流控制(Flow Control),根据具体情况适时调整发送的消息数。消息可靠性还能够通过对连接的验证管理连接自身,并在不需要连接时清除它们。

绑定与可靠性

WCF的可靠性是在绑定中控制与配置的。一个特定的绑定可以支持可靠消息传输(Reliable Messaging),也可以不支持它。如果支持,也可以通过设置为启用或禁用。何种绑定支持何种可靠性值,要根据绑定的目标场景而定。表1-2总结了绑定、可靠性、有序传递(Ordered Delivery)以及它们各自的默认值之间的关系。

表1-2:可靠性与绑定

名称               支持可靠性         默认可靠性           支持有序传递       默认有序传递

BasicHttpBinding          No               N/A                No              N/A

NetTcpBinding             Yes                Off                   Yes             On

NetPeerTcpBinding            No                N/A                No              N/A

NetNamedPipeBinding                No                N/A (On)             Yes             N/A (On)

WSHttpBinding             Yes                        Off                   Yes             On

WSFederationHttpBinding    Yes                Off                   Yes             On

WSDualHttpBinding          Yes               On                   Yes            On

NetMsmqBinding              No                N/A                 No             N/A

MsmqIntegrationBinding        No                 N/A                 No            N/A

BasicHttpBinding、NetPeerTcpBinding以及两种MSMQ绑定(NetMsmqBinding和MsmqIntegrationBinding)不支持可靠性。因为BasicHttpBinding面向旧的ASMX Web服务,是不具有可靠性的。NetPeerTcpBinding则为广播场景设计。MSMQ绑定针对断开调用,在任何情况下都不存在传输会话。

WSDualHttpBinding总是支持可靠性的,它能够保持回调通道,确保基于HTTP协议的客户端存在。

NetTcpBinding绑定以及各种WS绑定,默认情况下并不支持可靠性,但是允许启用对它的支持。由于NetNamedPipeBinding绑定总是拥有一个确定的从客户端到服务的跳数,因而它的可靠性是绑定固有的。

有序消息

消息可靠性确保了消息的有序传递,允许消息按照发送顺序而非接收顺序执行。此外,它保证了消息只会被传递一次。

WCF允许开发者只启用可靠性,而不启用有序传递。此时,消息按照接收它们的顺序进行传递。如果同时启用了可靠性与有序传递,则所有绑定的默认值均支持可靠性。

配置可靠性

通过编程方式或管理方式都可以配置可靠性(以及有序传递)。如果我们启用了可靠性,则客户端与服务宿主端必须保持一致,否则客户端无法与服务通信。我们可以只对支持它的绑定配置可靠性。例1-23所示的服务端配置文件,使用了绑定配置节,启用了TCP绑定的可靠性。

例1-23:启用TCP绑定的可靠性

<system.serviceModel>

   <services>

      <service name = "MyService">

         <endpoint

            address  = "net.tcp://localhost:8000/MyService"

            binding  = "netTcpBinding"

            bindingConfiguration = "ReliableTCP"

            contract = "IMyContract"

         />

      </service>

   </services>

   <bindings>

      <netTcpBinding>

         <binding name = "ReliableTCP">

            <reliableSession enabled = "true"/>

         </binding>

      </netTcpBinding>

   </bindings>

</system.serviceModel>

至于编程配置方式,TCP绑定和WS绑定提供了略微不同的属性来配置可靠性。例如,NetTcpBinding绑定接受一个Boolean型的构造函数参数,用来启动可靠性:

public class NetTcpBinding : Binding,...

{

   public NetTcpBinding(...,bool reliableSessionEnabled);

   //更多成员

}

我们只能在对象的构造期间启用可靠性。如果通过编程方式设置可靠性,需要创建支持可靠性的绑定对象:

Binding reliableTcpBinding = new NetTcpBinding(...,true);

NetTcpBinding定义了只读的ReliableSession类,通过它获取可靠性的状态:

public class ReliableSession

{

   public TimeSpan InactivityTimeout

   {get;set;}

   public bool Ordered

   {get;set;}

   //更多成员

}

public class OptionalReliableSession : ReliableSession

{

   public bool Enabled

   {get;set;}

   //更多成员

}

public class NetTcpBinding : Binding,...

{

   public OptionalReliableSession ReliableSession

   {get;}

   //更多成员

}

必备有序传递

理论上,服务代码和契约定义应该与它使用的绑定及属性无关。服务不应该考虑绑定,在服务代码中也不应该包含它所使用的绑定。不管配置的绑定是哪一种,服务都应该能够正常工作。然而实际上,服务的实现或者契约本身都会依赖于消息的有序传递(Ordered Delivery)。为了帮助契约或服务的开发者能够约束支持的绑定,WCF定义了DeliveryRequirementsAttribute特性:

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface

                AllowMultiple = true)]

public sealed class DeliveryRequirementsAttribute : Attribute,...

{

   public Type TargetContract

   {get;set;}

   public bool RequireOrderedDelivery

   {get;set;}

   //更多成员

}

DeliveryRequirements特性可以应用到服务一级,对服务的所有终结点施加影响,或者只对公开了特定契约的终结点施加影响;如果应用到服务一级,则意味着选用有序传递是根据具体实现作出的决策。DeliveryRequirements特性也可以应用到契约一级,它会对所有支持该契约的服务施加影响。这样一种在契约一级的应用,体现了对有序传递的要求是根据设计作出的决策。这一约束会在装载服务时得到执行与验证。如果一个终结点包含的绑定并不支持可靠性;或者支持可靠性,却被禁用了;或者虽然启用了可靠性,但却禁用了有序传递,那么装载服务就会失败,抛出InvalidOperationException异常。

注意:命名管道绑定符合有序传递的约束。

举例来说,如果不考虑契约,要求服务的所有终结点都启用有序传递,则可以将DeliveryRequirements特性直接应用到服务类上:

[DeliveryRequirements(RequireOrderedDelivery = true)]

class MyService : IMyContract,IMyOtherContract

{...}

通过设置TargetContract属性,只有支持目标契约的服务终结点才需要遵循可靠的有序传递的约束:

[DeliveryRequirements(TargetContract = typeof(IMyContract),

                      RequireOrderedDelivery = true)]

class MyService : IMyContract,IMyOtherContract

{...}

如果将DeliveryRequirements特性应用到契约接口上,则支持该契约的所有服务都必须遵循这一约束:

[DeliveryRequirements(RequireOrderedDelivery = true)]

[ServiceContract]

interface IMyContract

{...}

class MyService : IMyContract

{...}

class MyOtherService : IMyContract

{...}

RequireOrderedDelivery的默认值为false,如果只应用了DeliveryRequirements特性,没有设置RequireOrderedDelivery的值,则是无效的。例如,如下语句是等效的:

[ServiceContract]

interface IMyContract

{...}

[DeliveryRequirements]

[ServiceContract]

interface IMyContract

{...}

[DeliveryRequirements(RequireOrderedDelivery = false)]

[ServiceContract]

interface IMyContract

{...}

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论