级别: 初级 柴晓路 (fennivel@dealeasy.com), Chief Solution Architect, DealEasy
2002 年 7 月 01 日 SOAP应用模式是一个由四篇文章组成的系列,主要讨论的是如何将SOAP应用到各种各样的应用环境中去。本文是系列的第四篇,着重探讨如何在性能要求较高的领域通过事件驱动的增量解析处理方式以及缓存方式来减少响应时间,减少系统开销,增加系统吞吐量,同时最后还给出了一个处理非XML数据的方法。
SOAP消息的增量解析和处理
在SOAP消息的增量解析和处理模式下,SOAP发送者可能生成了一个非常冗长的SOAP消息,由于等到完整接收这个冗长的SOAP消息后再处理会造成大量的技术时间的浪费,并且将延迟响应速度,因此就需要发送者具备增量发送的能力,而接收者具备增量接收的能力。当SOAP接收者在接收消息的时候,使用一个能够增量处理消息体的SOAP处理器来实现这一目标(一般的,当消息体开始被接收的时候,开始使用一个SAX风格的XML解析器来处理)。
这种方法对于内存有限的SOAP处理器而言是特别的有效,同时对于那些面向增量的实时数据传输的服务而言也是非常的有效。另外它还适用于这样的应用场景:消息具备冗长的消息体,同时这些消息体能够通过SOAP处理器模块直接被转换成应用程序中的数据结构和事件。事实上,此时我们并没有必要为这些数据额外地构造相应的DOM模型,SAX方式的处理更为适合。在增量处理的情况下,对于SOAP数据模型的支持仍然是可能的,
如何这些模型是能够被增量地构造的话。
概括地说,本节所描述的SOAP消息的增量解析和处理模式需要接收者能够增量地解析和处理SOAP消息。这是一个适用于有限内存的处理环境的一个通用模式。如果SOAP Body包含了大量的数据,同时在具体应用中适合分段处理,那么通过SAX解析器采用增量处理模式是非常贴和需求的。下面的代码展示了一个可分段处理的SOAP请求消息示例,其中使用了BodyDataChunk元素来表示不同的数据段。
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
<env:Header>
<!-Set of headers processed before Body -->
</env:Header>
<env:Body>
<b:BodyDataChunk xmlns:s="http://example.org/2001/06/chunking">
<b:DataLength>1024</b:DataLength>
<b:Data>kfkk34jkhfSomeBase64EncodedDatajdsgkjgjajgo34093589uvsjv……………jhfjhf350giqhf</b:Data>
</b:BodyDataChunk>
<!- More BodyDataChunk elements -->
<b:BodyDataChunk xmlns:s="http://example.org/2001/06/chunking">
<b:DataLength>1024</b:DataLength>
<b:Data>oqjrj45cmoLastLotOfBase64EncodedData12r9vnhofjhckzlmxjws……………skfjk23ogkkjhq</b:Data>
</b:BodyDataChunk>
</env:Body>
</env:Envelope>
|
此时,如果SOAP请求是以流(stream)的方式被传输并被增量处理的话,那么相应的响应消息也可以以流的方式被传向初始的请求发送者。在这样的应用实例中,对于接受应用的设计,我们需要在实时性和错误处理方面格外加以重视。
如果SOAP请求的Header条目引发了错误的话,那么SOAP Fault将被插入到响应消息中,同时请求消息的处理也同时被中止。
SOAP消息的接受处理程序将会把每个BodyDataChunk元素视为一个原子。处理中,将视每个BodyDataChunk元素被成功处理与否,而将积极的或消极的确认加入到SOAP响应的流(stream)中去。当SOAP请求消息被处理完毕之后,SOAP响应消息的生成处理也同时被完成。
另一个可选择的方案是,SOAP接受处理程序可以当SOAP请求被完整接受完毕再处理每个BodyDataChunk元素。如果在接受之中发生错误,那么一个SOAP Body Fault元素将被加入到SOAP响应流中,同时SOAP请求的处理被中止。
缓存模式
在缓存(Caching)模式下,一些应用程序因为效率上的原因,例如为了获得更快的响应时间、占用更小的带宽或一些其他的方面,而进行可能的缓存操作。为了实现这一点,我们需要在相关的环境中设置缓存机制。例如,"读"缓存可以被SOAP中间介用于保存消息,以备在请求/响应消息交换模式的响应阶段重用。这样的缓存机制可以作用在整个消息的范围,也可以作用在一个SOAP模块的范围,或是作用在个别的SOAP模块的元素上。
类似的,当在请求/响应消息交换模式下(当然也可以是其他的消息交换模式),请求消息不需要被立即转发或者响应的话,"写"缓存就变得有用了。这种缓存机制同样可以作用在整个消息的范围,也可以作用在一个SOAP模块的范围,或是作用在个别的SOAP模块的元素上。
对于能够作用在不同元素上的缓存机制而言,它可以使用一个属性来关联目标缓存元素,具体的,属性可以通过XML Query的表达式或是XPath的表达式,在消息头或是文档中描述目标元素。同时缓存机制除指定目标结点外,还要制订一些其他的缓存参数,诸如生存时间(增量时间)、失效时间(绝对时间)、实体有效性、时间有效性、失效服务的订阅以及对象更新和清理等。
最后,一些应用程序还要求缓存机制具备描述消息元素之间的依赖和关系的能力。例如,一个响应消息中的元素可能适用于一个较大范围的请求消息,如果能够描述该元素与那些请求元素的关联关系将会对处理有帮助,如此,在应付这些请求的时候,我们就可以使用一个经济的方式(使用缓存元素)来给出响应消息。
缓存机制经常在分布式系统中作为优化机制而使用。它可以用于避免重复执行相同的计算操作,或是避免当结果集在一段时间内持续有效的前提下重复执行复杂的数据库访问。此时,一系列针对相同信息的请求可以使用被缓存的版本来响应,而无需重复地处理并占用系统开销。缓存机制的另一个用途则是针对数据的传输,应用了缓存机制之后,数据的副本可以存于叶节点服务器以方便本地的服务,而无需重复地访问中央信息库。如此,不仅加快了对信息的访问,同时缩减了对网络带宽的占用,同时还减轻了中央服务器的负载。缓存机制可以以底层传输架构的一部分被提供使用,不过在本节描述的应用模式中,我们假设这个缓存机制是与任何底层传输相独立的。
本应用模式的一个例子是,当一系列请求可以安全地以相同的结果返回的时候,缓存对应于该请求的响应消息。BizCo是一家销售软件产品的在线商场,它每天上午8:00更新它的在线产品报价数据库,那么在上午8:00之后访问该商场的SOAP报价服务的远程用户都可以缓存报价消息直至第二天上午8:00。如果远程客户需要重复访问相同产品的报价的话,它就不需要重复地访问远程的BizCo的SOAP报价服务,而只需要从本地的缓存中使用缓存下的版本。在本地缓存中的所有数据在第二天的更新时间(8:00)之前会被全部清空。图1展示了一个可能的实现体系架构。
Figure 1.?? 缓存模式
其中,SOAP应用A初始化了一个对产品价格目录的询价请求,具体的SOAP消息如下:
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
</env:Body>
<c:CatalogPriceRequest xmlns:c="http://example.org/2001/06/catalog">
<c:PartNumber>ABC-1234</c:PartNumber>
</c:CatalogPriceRequest>
</env:Body>
</env:Envelope> |
缓存中间介SOAP应用B无法依靠其本地的缓存数据库来满足请求,因此它将该请求转发并最终到达询价目录服务SOAP应用C。该服务处理了这个请求,并且将被请求的报价信息装配在响应消息中。在响应消息中,被添加了一个额外的SOAP Header条目,用于在返回的消息路径上控制所有的缓存服务模块。这个CacheControl SOAP Header条目包含了一个CacheKey元素和一个Expires元素,CacheKey元素被用于在以后的请求发生时,用于匹配被缓存的响应,而Expires元素则设置了本地的副本应当在何时被清理(失效)。这个响应消息将通过缓存中间介被返回。
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
<env:Header>
<ca:CacheControl xmlns:ca="http://example.org/2001/06/cache">
<ca:CacheKey>ABC-1234</ca:CacheKey>
<ca:Expires>2001-03-09T08:00:00Z</ca:Expires>
</ca:CacheControl>
</env:Header>
<env:Body>
<c:CatalogPriceResponse xmlns:c="http://example.org/2001/06/catalog">
<c:PartNumber>ABC-1234</c:PartNumber>
<c:PartPrice c:currency="EUR">120.37</c:PartPrice>
</c:CatalogPriceResponse>
</env:Body>
</env:Envelope>
|
在缓存中间介上,CacheControl SOAP Header条目被用于生成响应消息的本地副本,这个副本可以通过键值CacheKey来标识和访问。同时该副本将在Expires元素所描述的时间被清理出缓存。然后,CacheControl元素被中间介从响应消息中剔除,而报价信息则被返回给最初的请求发送者。从最初的SOAP发送者到最终的SOAP接受者的完整请求/响应消息路径即为图1中的消息路径1。
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
<env:Body>
<c:CatalogPriceResponse xmlns:c="http://example.org/2001/06/catalog">
<c:PartNumber>ABC-1234</c:PartNumber>
<c:PartPrice c:currency="EUR">120.37</c:PartPrice>
</c:CatalogPriceResponse>
</env:Body>
</env:Envelope>
|
当产品ABC-1234的报价信息被缓存在中间介的缓存数据库中后,后继的针对产品ABC-1234的询价SOAP请求就能够被中间介所满足了,此时,实际的SOAP消息路径就变成了图1中较短的请求/响应消息路径2。
发送非XML数据
发送非XML数据的模式一般适用于这样的应用背景:数码相机期望能够使用SOAP消息机制通过无线网络连接来将图象数据传送给远程服务器。在SOAP消息中将包含二进制图象数据(非XML)。这个数码相机的应用实例呈现了一个特别的应用情况,此时从接收者到发送者的网络连接是无法建立的,这是因为数码相机这个设备不具备接收连接的能力,当然在其他类似的情形下,可能是因为防火墙的原因。
对非XML数据的支持在一些相关的技术文献中已经被提及,"SOAP with Attachments"是一个由W3C接收的规范草稿,其中描述了如何使用类似Email附件的形式在SOAP消息交换中传输非XML的附件。在SOAP规范中也提供了Base64编码的数据类型,以进行少量的非XML数据的传输。其中"SOAP with Attachments"规范已经被ebXML消息服务规范接收为定义具备非XML数据支持的消息结构的基础架构。具体的,支持非XML数据需要有一些额外的消息包装机制,多片断MIME结构是一种适用的包装机制,这种机制将影响和作用于消息与底层通讯协议的绑定。在具体传输时,多个非XML的数据流将被表述成多个MIME结构,也就是形成了多片断的MIME结构。而图中实现的消息装载处理器将生成对这个多片断MIME数据包的一组引用标识,每个引用指向一个MIME片断部分,在SOAP消息正文中,将使用片断标识来引用这些MIME片断。
Figure 2.?? 使用MIME包装非XML数据
图2演示了如何使用多片断MIME来包装消息的不同组成部分。其中,最外层的MIME信封包装了一组MIME片断个体。第一个MIME片断包含了一个SOAP消息,这个SOAP消息包含了一个由消息装载处理器创建的"装载SOAP Header条目"。第二个及其后面的MIME片断所包含的消息负载可以是XML文档,也可以是其他的MIME内容类型的内容,诸如图象、声音或是视频数据等。"装载SOAP Header条目"可以包含引用独立MIME片断的引用标识,这个引用标识与MIME片断的内容标识是相一致的。在下面的例子中,我们是使用XLink引用来实现的。XLink role属性可以被用于进一步区分在消息负载中包含的数据的类型。
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
<env:Header>
<n:Manifest xmlns:n="http://example.org/manifest">
<n:Reference n:id="image01"
xlink:href="cid:payload-1"
xlink:role="http://example.org/image">
<n:Description>My first holiday photograph</n:Description>
</n:Reference>
<n:Reference n:id="image02"
xlink:href="cid:payload-2"
xlink:role="http://example.org/image">
<n:Description>My second holiday photograph</n:Description>
</n:Reference>
</n:Manifest>
</env:Header>
<env:Body>
-----
</env:Body>
</env:Envelope>
|
参考资料
关于作者  | 
|  |
柴晓路: 上海得易信息技术有限公司(
DealEasy)首席系统架构师、XML Web Sevices技术顾问,
WS-I Working Group成员,
UDDI Advisory Group成员,
UDDI-China.org创始人,IBM developerWorks专栏作家。2000年获复旦大学计算机科学硕士学位,曾在国际计算机科学学术会议(ICSC)、亚太区XML技术研讨会(XML Asia/Pacific'99)、中国XML技术研讨会(北京)、计算机科学期刊等各类国际、国内重要会议与期刊上发表论文多篇。专长于Web Services技术架构、基于XML的系统集成和数据交换应用及方法,同时对数据库、面向对象技术及CSCW等技术比较擅长。
|
对本文的评价
|