在《实例篇》中,我通过可靠会话实现了对图片的可靠、有序的传输;在《概念篇》中,我们对可靠消息涉及到的可靠消息传输(RM)的相关概念进行了讲述。在WS-*大家庭中,WS-RM为可靠消息传输提供了一个一个规范,使互操作成为可能。在《协议篇》中,我们侧重对WS-RM的介绍。
WS-RM,为WS-Reliable
Messaging的简称,是WS-*大家庭的一个重要成员。和前面介绍的WS-Coordination和WS-AT一样,WS-RM的制定者是结构化信息标准促进组织(OASIS:Organization
for the Advancement of Structured Information Standards)。
制定WS-RM的一个主要目的就是创建一个模块化的实现可靠详细传输(Reliable
Messaging)的机制。WS-RM定义了一种消息传输协议(Messaging
Protocol),以实现在可靠消息传输过程中对消息的识别、追踪和管理。并在此基础上,定义了SOAP绑定实现了互操作。到目前为止,WS-RM先后出了两个官方版本,即WS-RM
1.0和WS-RM 1.1。接下来对WS-RM的介绍完全基于WS-RM 1.1版本。WS-RM
1.1的命名空间为http://docs.oasis-open.org/ws-rx/wsrm/200702,你也可以直接通过命名空间表示的URL查看WS-RM官方文档。
一、 可靠消息传输模型
在本节刚刚开始的时候,我们就简单讨论了可靠消息传输需要解决的问题,或者说通过可靠消息传输可以实现的目标。概括性的说,可靠详细传输可以来实现一下三个可靠性述求:接收保障、重复筛选和有序交付。接收保障确保从消息源发送的消息能够成功地抵达目的地;重复筛选意味着消息的接收端能够识别每一个接收到的消息,自动丢弃重复的消息;而有序交付要求消息的接收端能够完全按照消息发送的顺序上对消息进行交付。
具体来说,我们可以通过如图1所示的可靠消息传输模型来说明。整个可靠消息传输体系最终是为应用服务的。如果我们将发送消息的称为应用源(Application Source),将接收消息的应用称为应用目的地(Application Destination),那么可靠消息传输题是为了确保应用源和应用目的地之前消息传输的可靠性而存在。
图1所示的可靠消息传输模型向读者展示了一个简单的消息可靠传输的流程。在消息发送端,应用源将消息发送给本地的可靠消息传输体系,即可靠消息传输源源(RM Source,以下简称RM源);RM源将消息发送到目的地;可靠消息传输目的地(RM Destination,以下简称RM目的地)接收到消息之后,会像RM源发送确认(ACK)消息,表明消息已经被成功接收;如果消息准确无误(这里主要指消息序号是否和上次交付的消息相邻),则将消息交付给应用目的地。
图1 可靠消息传输模型
和TCP实现对报文段的可靠传输一样,在这依然采用消息缓存、消息确认和超时重传的机制提供对可靠消息传输的三个目标的实现。首先,当消息从应用源发送到RM源之后,会被赋予一个消息序号,该序号在该可靠消息传输上下文中是唯一的。RM源和目的地具有各自的消息缓冲区,或者说消息窗口对消息,用户缓存消息之用。RM源用该消息窗口存放已经发送但是尚未接收到确认的消息,我们可以将这样的消息成为状态未决消息(In-Doubt
Message);RM目的地则利用消息窗口存放成功接收但是尚未向应用目的地交付的消息。
对于某个已经发送的消息,如果在设定的超时时限内没有成功接收到相应的确认,RM源会认为该消息发送失败。此时,它会从自己的消息窗口中选择对应的消息进行重新发送。只有在成功接收到确认消息的情况下,RM源才会将消息从消息窗口中移除。
当RM目的地成功接收到消息后,如果消息的序号和上次交付消息的序号相邻,它会将消息交付给应用目的地。否则,表明之前发送出来的消息尚未抵达,此时RM目的地会将该消息放到自己的消息窗口中。只有等到之前所有的消息全部成功接收后,RM目的地采用按照消息的序号对消息实施交付,从而保证了对消息的有序交付。如果,接收到的消息序号小于已经交付的消息序号,或者等于消息窗口的某个消息的序号,RM目的地将其视为重复消息予以丢弃。
WS-RM仅仅是对消息窗口所应提供的功能进行规定,并没有对消息缓存的具体实现做出任何的限制。也就是说,我们可以采用基于内存的方式将消息缓存在当前进程的内存之中,这样可以带来更好的性能提升;我们也可以采用持久化的存储方式,将序列化后的消息存储于物理存储介质中,这样可以实现跨进行的数据共享已及程序中断后的数据恢复。前者被WCF中的可靠会话所采用。
二、从消息交换来看可靠消息传输的处理流程
上面我们通过对WS-RM采用的可靠消息传输模型进行了介绍,相信大家对基本的实现机制有了一个大致的了解。接下来,我们将目光聚焦到具体的消息交换层面,看看WS-RM采用怎样的消息交换方式提供对消息确认、超时重传的实现。不过,在这之前我们必须先介绍一个非常重要的概念:序列(Sequence)。
可靠消息传输致力于对在两种终结点之间提供对接收保障、重复筛选和有序交付的实现,但是可靠消息传输具有一个执行范围。或者说,可靠消息传输的实现是基于某个上下文环境中,这相对于是一种会话(Session)的概念,这个会话在WS-RM的词汇中被称为序列。两个终结点之前能够实现可靠消息传输之前,需要先在它们之间创建一个序列,该序列为可靠消息传输提供一个执行上下文。
我们同样用TCP对报文段的可靠传输作为类比。TCP是一个完全基于连接的协议,在利用TCP进行报文传输的之前,两个TCP端点之间需要通过3次“握手”建立连接。也就是说,TCP对报文段的可靠传输是在一个确立的连接中进行的,TCP连接担当执行上下文的作用。所以,TCP连接至于TCP报文的可靠传输,就相当于序列对WS-RM可靠消息传输。
通过前面的介绍,我们知道可靠消息传输机制的核心应该是“消息窗口”和“消息识别”。为了让RM源和目的地能够有效地识别每一个消息,每一个消息会被赋予一个消息序号(Message Number)。该消息序号从1开始,并在可靠消息序列这个上下文中是唯一的。
对WS-RM下的序列有了一个大致的了解之后,我们结合图5-2所示的序列图(Sequence Diagram)讨论一下WS-RM下的消息确认机制和超时重传是如何实现的。如图2所示,基于WS-RM消息交换的两个终端是Endpoint A和Endpoint B,它们分别是消息的最初发送者和最终接受者。整个过程由10个步骤完成,接下来我们来介绍一下每一个步骤具体完成怎样的工作:
步骤1-2:Endpoint
A向Endpoint B发送一个创建CreateSequence的请求,Endpoint
B创建一个全新的序列,并将序列的唯一标识(http://www.artech.com/abc)以CreateSequenceReponse的形式返回给Endpoint
A;
步骤3-5:Endpoint A连续向Endpoint
B发送3个消息,这3个消息均具有WS-RM相关的报头,主要包括序列的唯一标识和消息序列(消息序号分别文1、2和3)。为了避免频繁的网络传输,WS-RM的消息会确认机制采用一种批量确认的机制。也就是说,RM目的地对它所接收的消息并不是逐个确认的,而是将之前接收到的消息序号方式一个确认范围(Acknowledgement
Range)中,一并发送给RM源进行批量确认。反映在RM源上,如果它期望在某次消息发送后期望接收到对方的确认,就需要在该消息中插入一个AckRequested报头。步骤5中发送的第三个消息就是包含了这么一个消息报头;
步骤6:假设Endpoint B先后接收到序号为1和3个两个消息,第二个消息在传输过程中被丢弃。当接收到包含有AckRequested报头的消息之后,会向Endpoint A发送确认消息。在确认消息中的确认范围中,包括1和3;
步骤7:Endpoint A接收到确认消息后,分析确认范围中的消息序号,发现并不存在2,直到序号为2的消息发送失败。于是会从发送窗口中提取序号为2的消息,进行重传,该消息同样具有AckRequested报头,因为它期望及时接收到对重传消息的确认;
步骤8:Endpoint B成功接收到重传的序号为2的消息后,发送确认消息进行确认,需要注意的是确认范围中不仅仅包含2,还包括之前成功接收的消息序号1和3;
步骤9-10:Endpoint A接收到确认。如果此时不需要进行后续的消息交换工作,可以发送TerminateSequence消息请求终止序列,Endpoint B对序列实施终止,并返回TerminateSequence消息进行终止确认。
图2 WS-RM消息交换
作者:蒋金楠
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。