WCF技术内幕之消息交换模式、拓扑和编排


    当设计消息应用系统的时候,有必要考虑消息是怎样在发送者、中介者和接收者之间流转的。系统中消息交换可能的波动值可以被不同程序地详细描述。这些不同级别的描述信息技术众所周知的消息交换模式、消息拓扑和消息编排。

消息交换模式

    描述消息交换最常用的度量标准就是消息交换模式。消息交换模式是"描述信息参与者之间交换消息的模板。" 消息交换模式被限制在发送者和接收者之间的逻辑连接上,整个行业也已经接受了这个事实。从概念上说,消息交换里的应答需要发送者侦听一个存在的连接或一个新的连接上。更确切的说,也许电话和无线通话有所不同,但是在面向服务的世界里通常有三种类型的消息交换模式:数据报、请求/应答和双工。

    数据报交换模式

        图3-1说明了数据报消息交换模式,也称为simplex(单一模式)。这个消息交换模式表示一个单向的消息发送,或即发即弃的消息发送。使用这个消息交换模式的消息发送称为数据报消息交换模式。


图 3-1 数据报消息交换模式

        数据报消息交换模式使用WSDL语言描述为一个包含wsdl:input和没有wsdl:outout元素的操作。例如,下面的WSDL代码块描述了一个可以接收输入的操作。

<wsdl:portType name="ISomeContract" ...>
  <wsdl:operation name="SomeOperation">
    <wsdl:input wsa10:Action="urn:SomeActionInput" .../>
  </wsdl:operation>
</wsdl:portType>

        创建一个使用数据报消息交换模式的WCF程序是相当简单的事情。通常会以契约定义开始:

using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Xml;

[ServiceContract(Namespace = "http://wintellect.com/SomeContract",
    Name = "ISomeContract")]
public interface ISomeContract
{
    [OperationContract(Name = "SomeOperation",
        Action = "urn:SomeActionInput",
        IsOneWay = true)]
    void SomeOperation(Message message);
}

这个例子里有两个重要的东西:SomeOperation方法的Void返回类型和OperationContractAttribute属性的IsOneWay标记。

        因为正在使用C#接口去描述一个数据报消息操作,所以需要使用一个返回类型来表明这是一个单向操作。用来描述数据报消息操作的方法必须有一个Void放回类型。指定别的返回类型,WCF在验证契约的时候回抛出一个InvalidOperationException异常的消息。

        当定义一个数据报操作时,只定义一个带Void放回类型的接口是不够的。考虑下面的契约:

using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Xml;

[ServiceContract(Namespace = "http://wintellect.com/SomeContract",
    Name = "ISomeContract")]
public interface ISomeContract
{
    [OperationContract(Name = "SomeOperation",
        Action = "urn:SomeActionInput",
        ReplyAction = "urn:SomeActionOutput")]
    void SomeOperation(Message message);
}

这个契约最终的WSDL信息如下:

<wsdl:portType name="ISomeContract" ...>
  <wsdl:operation name="SomeOperation">
    <wsdl:input wsaw:Action="urn:SomeActionInput" .../>
    <wsdl:output wsaw:Action="urn:SomeActionOutput" ...=""/>
  </wsdl:operation>
</wsdl:portType>

        wsdl:output元素的出现表示应该有消息回复发送者。在WCF里,唯一避免回复消息的方法就是在操作属性里设置IsOneWay属性。默认值为false,这个设置让操作默认使用请求/应答消息交换模式。

        数据报消息交换模式还涉及了一个有趣的面向服务的错误处理手法。错误可以被序列化为SOAP错误消息,并且这些错误消息可以被发送到指定的终结点上。如果发送者希望接收这些消息或发送到其他的终结点,发送者必须在消息头块里<FaultTo>指定地址,然后接收者尽全力把错误消息发送给指定的终结点。

    请求/应答消息交换模式

        从广义上说,Internet是建立在请求/应答消息交换模式上的,同样被称我半双工。

        图3-2从概念上说明了请求/应答消息交换模式。


图 3-2 请求/应答消息交换模式

        请求/应答消息交换模式使用WSDL表述为一个包含wsdl:input和wsdl:output元素的操作。例如,下面的WSDL代码块描述的就是一个请求/应答消息交换模式:

<wsdl:portType name="ISomeContract" ...>
  <wsdl:operation name="SomeOperation">
    <wsdl:input wsaw:Action="urn:SomeActionInput" .../>
    <wsdl:output wsaw:Action="urn:SomeActionOutput" ...=""/>
  </wsdl:operation>
</wsdl:portType>

        注意,代码里的wsdl:input和wsdl:output元素的顺序暗示了在一个应答消息发送邀请,请求消息必须先被接收。

        WCF操作契约默认使用请求/应答消息交换模式。任何WCF认为可序列化的类型都可以指定一个返回类型。比如,下面的契约使用请求/应答消息交换模式:

using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Xml;

[ServiceContract(Namespace = "http://wintellect.com/SomeContract",
    Name = "ISomeContract")]
public interface ISomeContract
{
    [OperationContract(Name = "SomeOperation", 
        Action = "urn:SomeActionInput", 
        ReplyAction = "urn:SomeActionOutput")]
    void SomeOperation(Message message);
}

        有些传输,如用户报文协议(UDP)和MSMQ,本质上都是单向的。当WCF最初发布的时候,还没有对于使用MSMQ的请求/应答消息交换模式的直接支持。在前面的“面向服务”中可以得出,有几个可以定义接收者发送回复(ReplyTo)或错误消息的WS-Addressing消息头块。当使用像TCP、HTTP或命名管道这样的传输时,接收者可以通过反向通道发送应答消息。

    双工消息交换模式

        双工是指同时发送和接收消息,是一种在电话通话里见到的交互方式。在消息应用里,双工消息交换模式定义了一个允许接收者和发送者同时发送消息的操作集合,反之亦然。图3-3说明了双工消息交换模式。


图 3-3 双工消息交换模式

        在双工消息模式里,发送者和接收者可以自由地发送消息。与双工消息交换模式相关的WSDL包含两个操作:一个操作表示消息发送给接收者,另外一个操作表示消息从接收者回发给发送者。

<wsdl:portType name="ISomeContract" ...>
  <wsdl:operation name="SomeOperation">
    <wsdl:input wsa10:Action="urn:SomeActionRequest" .../>
  </wsdl:operation>
  <wsdl:operation name="SomeCallbackOperation">
    <wsdl:output wsa10:Action="urn:SomeCallbackRequest" ...=""/>
  </wsdl:operation>
</wsdl:portType>

        从某种意义上讲,双工消息交换模式是其他消息交换模式的结合。换句话说,一个消息报可以从发送者发送给接收者,反之亦然。考虑下面代码

<wsdl:portType name="ISomeContract" ...>
  <wsdl:operation name="SomeOperation">
    <wsdl:input wsaw:Action="urn:SomeActionRequest" .../>
    <wsdl:output wsaw:Action="urn:SomeContractReply" ...=""/>
  </wsdl:operation>
  <wsdl:operation name="SomeCallbackOperation">
    <wsdl:output wsaw:Action="urn:SomeCallbackContractRequest" ...=""/>
    <wsdl:input wsaw:Action="urn:SomeCallbackContractReply" ...=""/>
  </wsdl:operation>
</wsdl:portType>

        SomeOperation操作描述了从发送者到接收者(urn:SomeActionRequest)和接收者回发给发送者(urn:SomeContractReply)的消息。SomeCallbackOperation操作表示从接收者到客户端(urn:SomeCallbackContractRequest)和回发给接收者(urn:SomeContractReply)的消息。

        WCF契约创建双工消息交换模式在语法上有些奇怪。如前面所描述的,双工通信需要两个契约。习惯上,描述发送给接收应用程序的消息(和应答消息,如果有)的契约称为服务契约,描述接收者发送给发送者的契约称为回调契约。这两个契约通过服务契约的ServiceContractAttribute.CallbackContract属性关联,如下所示:

using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Xml;


//服务契约定义类似
//只是加了CallbackContract属性
//也可以设置IsOneWay=true
[ServiceContract(Namespace ="http://wintellect.com/SomeContract",
    Name = "ISomeContract",
    CallbackContract =typeof(ICallbackContract))]
public interface ISomeContract
{
    [OperationContract(Name = "SomeOperation",
        Action ="urn:SomeActionRequest",
        ReplyAction ="urn:SomeContractReply")]
    void SomeOperation(Message message);
}
//callback contract 上不需要ServiceContract
//也可设置IsOneWay=true
public interface ICallbackContract
{
    [OperationContract(Name ="SomeCallbackOperation",
        Action ="urn:SomeCallbackContractRequest",
        ReplyAction ="urn:SomeCallbackContractReply")]
    void SomeCallbackOperation(Message message);
}


消息拓扑

    消息拓扑描述的是在一个或多个发送者和接收者之间如何发送消息。消息拓扑可以描述为简单的应用-应用的连接,但是它同样可以描述为复杂的应用-企业的连接。

    某种层次上,消息拓扑是一个或多个消息交换模式的组合。实际上,可能存在有无数种拓扑结构,但通常接收的分类有4个:点对点、数据报点对点、消息转发代理和对等网络(P2P)。

    点对点

        点对点拓扑最简单且是被广泛使用的消息拓扑,是消息拓扑的一个基本组成部分。简单来说,点对点拓扑是指一个发送者和一个接收者交换消息。这个消息交换可以使用数据报、请求/应答或双工消息交换模式实现。

    只进点对点

        只进点对点拓扑是一个发送给不同参与者的数据报链。重要的是,要知道这个拓扑仅由数据报消息交换模式组成。消息有可能要返回给参与者,但是在消息里明确标记返回地址比含蓄描述更好,就像请求/应答发方式一样。通常,这个拓扑要依赖<From>、<ReplyTo>、<FaultTo>、<RelatesTo>、<MessageID>和<To> WS-Addressing消息头块来实现,如图3-4所示。


图 3-4 只进点对点消息拓扑

    消息转发代理

        一个消息转发代理是一个转发消息到其他终结点的消息参与者。消息转发代理能够根据处理规则决定消息何时、何地并且如何发送给其他消息参与者。一个消息转发代理拓扑可以细分为分布式消息转发代理、集中式消息转发代理和混合消息转发代理,这个消息转发代理很像现在使用的不同邮件服务拓扑。在SOAP里,消息中转代理是一个中介者,但它可以直接标记地址。图3-5说明了一个基本的消息转发拓扑。


图 3-5 消息转发拓扑

    对等网络

        一个真正的P2P应用是可以直接与其他P2P应用通信的。P2P应用可以与其他P2P应用通过一对一、一对多和多对多方式通信。P2P应用无须依赖服务器,因为它们可以通过网络(Mesh)直接通信。网络(Mesh)是一个指定的、可发现的和自维护的网络节点集合。在参与P2P消息交换以前,参与者必须先加入网络。通常,虽然P2P消息拓扑在参与者之间提供了丰富的交互能力,但是它仍然有很强的可伸缩性和弹性。图3-6展示了一个P2P拓扑结构。


图3-6 对等网络(P2P)拓扑

消息编排

    消息编排表示一个逻辑操作的消息交换集合。当使用信用卡给爱人或其他重要的人买礼物的时候,就参与了一个消息编排。这个买卖的逻辑操作由几个消息交换组成。

    1.商店发送信息给商业服务。

    2.商业服务发送数据给银行。

    3.银行发送一个批准码。

单独来看每个数据交换都没什么意义,但从总体来看,它们表示一个逻辑操作。

消息编排在面向服务的应用系统里起着关键作用,特别是在安全性、可靠性和事务性方面。当提供以消息为中心的安全时,要考虑发送者和接收者如何签名和加密消息。当提供可靠时,必须考虑收到消息时接收者如何和发送者通信。同样,在事务处理中,在事务处理中,必须考虑事务里的参与者如何表示操作已经成功提交。所以这些考虑需要一个定义良好的消息编排。




猜你喜欢

转载自blog.csdn.net/qq_33931656/article/details/80330135