且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

WCF中的可信赖会话

更新时间:2022-09-16 14:38:24

如果需要保证消息的传输正确性,以及传输的消息顺序,在WCF中的实现非常容易,即使用可信赖会话ReliableSession,前提是我们应该选择正确的绑定。支持可信赖会话的绑定包括WSHttpBinding,WSDualHttpBinding,WSFederationBinding以及NetTcpBinding和NetNamedPipesBinding(该绑定使用IPC协议,按照Juval Lowy的说法,该绑定的类名并不合理。绑定的类名通常根据协议命名,而不是根据它所采用的技术,例如NetTcpBinding而不是NetSocketBinding。因此IPC绑定应命名为NetIPCBinding,而不是NetNamedPipesBinding)。其中,与WS-*相关的绑定需要手动打开可信赖会话。

由于绑定可以采用配置方式设定,因此,是否增加可信赖传输与具体的服务契约代码无关。此外,绑定的选择同样可以通过配置文件修改,这就保证了WCF实现的灵活性。配置可信赖会话的方式如下所示:

<wsHttpBinding>
    <binding name="reliableBinding" receiveTimeout="00:20:00">
        <reliableSession enabled="true" ordered="true" inactivityTimeout="00:20:00"/>
    </binding>
</wsHttpBinding>

在配置文件中,让人疑惑不解的是两个超时值的设置。两者代表了不同的含义。receiveTimeout与应用程序消息相关,而inactivityTimeout则与应用程序以及基础架构消息相关。举例来说,如果一个服务契约包含了三个服务操作,且这三个操作将形成一个有序的序列(传输的消息顺序与此相关),那么计算非活动状态的值,对于前者而言是从调用服务对象的某一个操作之后开始计算,而后者则针对整个序列的操作。根据MSDN的解释,基础架构消息是指为了通道堆栈中的协议之一(例如,保持活动状态或确认,而并非包含应用程序数据)而生成的消息。

在可信赖会话中,任何一个超时值计时器触发都会断开连接,因此单独改变其中某一个的值是没有意义的。如果值不相同,则取两个值之间的最小值。他们的默认值均为10秒。

ReliableSession的Ordered属性保证了消息的传输顺序。它不意味着我们在调用服务对象时,必须遵循操作调用的顺序,而是指消息在发送时,必须按照调用的顺序传送。例如一个服务契约定义了M1,M2,M3三个服务操作。如果服务对象的调用顺序如下所示:

m_proxy.M1();
m_proxy.M2();
m_proxy.M3();

则消息的顺序为M1-> M2 -> M3。如果修改操作的调用顺序如下:

m_proxy.M3();
m_proxy.M2();
m_proxy.M1();

则消息的顺序为M3-> M2 -> M1。因此,我们应注意它与所谓的“分步操作(Demarcating Operation)”的区别。分步操作通过在[OperationContract]中指定IsInitiating和IsTerminating的值,标示操作的调用顺序。在DevX的一篇文章中有如下的服务契约定义:

[ServiceContract]
public interface IChopstickBuilder
{
    [OperationContract]
    int GetChopsticksUnderConstruction();

    [OperationContract]
    void WarmupChopstickMachine();

    [OperationContract]
    void ConstructAChopstick();
}

其中要求WarmupChopstickMachine()必须在ConstructAChopstick()操作之前调用。为保证客户端调用不出现顺序的错误,单单启动可信赖会话的有序传递仍嫌不足。此时,我们可以为WarmupChopstickMachine()操作定义分步操作:

[OperationContract(IsInitiating = true)]
void WarmupChopstickMachine();

不过,这样的操作定义实际上是无效的,因为IsInitiating的默认值本身就是true,这样的设置与不设置的效果完全一致。因此,我们可以考虑对ConstructAChopstick()和GetChopsticksUnderConstruction()进行设置:

[ServiceContract(SessionMode = SessionMode.Required)]
public interface IChopstickBuilder
{
    [OperationContract(IsInitiating = false, IsTerminating = true)]
    int GetChopsticksUnderConstruction();

    [OperationContract]
    void WarmupChopstickMachine();

    [OperationContract(IsInitiating = false)]
    void ConstructAChopstick();
}

使用分步操作需要会话的支持,因此需要在服务契约上将SessionMode设置为Required,否则会抛出InvalidOperationException异常。

对于某些严格要求可信赖会话的服务,为避免配置文件中错误设置可信赖会话的可能,可以强制要求WCF检查包含该服务契约的终结点,确认它是否选择了支持可信赖会话的绑定,并支持有序传递:

[ServiceContract(SessionMode = SessionMode.Required)]
[DeliveryRequirements(RequireOrderedDelivery = true)]
public interface MyReliableService...









本文转自wayfarer51CTO博客,原文链接:http://blog.51cto.com/wayfarer/280107,如需转载请自行联系原作者