摘要:本文概要说明了在通过 SOAP 进行 RPC 调用时当前实际存在的互操作性问题,同时讨论了导致互操作性问题的三个
因素:HTTP 问题、XML 问题和 SOAP 间断性。
目录
简介
什么是 SOAP?
常见的互操作性问题
传输问题
XML 问题
SOAP 问题
后续话题
简介
当前有多种创建应用程序的平台。但每种平台都习惯于使用自身的协议(本质上通常是二进制代码)来实现机器间的集
成。因此,跨平台的应用程序在数据共享方面的能力相当有限。认识到这些限制后,人们一直在致力于建立有关数据格式
和数据交换方面的标准,藉此以实现“不论服务采用何种软件,使用何种硬件,都能够跨越这一传统的界限以 Web 的形式
无缝地将它们集成在一起”这一远景目标。目前,这一目标已迅速发展成为一种新的计算范例。
该目标的核心是互操作性概念,即不同系统能够无缝地进行通信和共享数据。这也是 Web 服务追求的目标。Web 服务是一
种可以用标准 Internet 协议来访问的可编程应用逻辑;从另一个角度来说,Web 服务是有关机器间和应用程序间透明通
信的、借助于 Web 的标准的具体实现。
目前,实现机器间消息传递的 Web 服务技术多种多样,例如简单对象访问协议 (Simple Object Access Protocol,
SOAP)、Web 服务说明语言 (Web Service Description Language, WSDL) 和超文本传输协议 (HyperText Transfer
Protocol, HTTP)。这些消息的复杂程度各不相同,既有简单的方法调用,也有复杂的订单提交。在 Web 服务的功能中,
最一般但又较高级的功能是实现 RPC(远程过程调用)形式的通信(通过 RPC,一台计算机上的程序可以执行另一台计算
机的程序。)本文从实用的角度介绍了在使用 SOAP 进行 RPC 形式的通信时当前常见的互操作性问题,以后还将撰文探讨
有关通过 SOAP、WSDL 以及其它协议传送消息的问题。
图 1:Web 服务路线图:有线协议元素、服务说明和发现
什么是 SOAP?
SOAP 是 Simple Object Access Protocol(简单对象访问协议)的缩写。该协议的当前版本为 1.1,其具体规范发布在下
列站点上: www.w3.org/tr/soap(英文)。SOAP 以 XML 为基础,说明了机器间通信的消息传送格式。此外,它还包括几
个可选部分,用于描述方法调用 (RPC) 和详细说明通过 HTTP 发送 SOAP 消息的方法。(有关 SOAP 和 Web 服务的详细
背景知识,请参见 Web 服务的平台(英文)。)
以下是一个典型的 SOAP 请求(包括 HTTP 标头),它请求名为 EchoString 的 RPC 方法调用,并将一个字符串当作参
数:
POST /test/simple.asmx HTTP/1.1
Host: 131.107.72.13
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://soapinterop.org/echoString"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://soapinterop.org/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:echoString>
<inputString>string</inputString>
</tns:echoString>
</soap:Body>
</soap:Envelope>
如上所示,该请求将方法名编码为 XML : <tns:echoString>,将字符串参数编码为 <inputString>。它所代表的 C# 方法
类似于以下内容:
public String echoString(String inputString);
以下是来自服务器的响应:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://soapinterop.org/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:echoStringResponse>
<Return>string</Return>
</tns:echoStringResponse>
</soap:Body>
</soap:Envelope>
有关序列化字符串数据类型以及方法调用形状的规则在 SOAP 1.1 的第 5 节和第 7 节 (www.w3.org/tr/soap(英文))
中定义。
常见的互操作性问题
当执行 RPC 形式的 SOAP 消息传送时,可能会因为多种原因导致互操作性问题。有趣的是,许多互操作性问题都不是
SOAP 本身的问题,而是基本传输引擎或 XML 引擎所导致的互操作性问题。也就是说,互操作性问题可能是:
HTTP 问题
XML 问题,或
SOAP 间断性
还应指出的是,这些规范的制定者也有考虑不周的地方,他们有时可能会模棱两可,这样就很难确定唯一正确的行为。
传输问题
XML Web 服务消息的核心在于发送消息的传输机制。当通过 SOAP 进行 RPC 调用时,HTTP 是目前最为常用的传输机制。
这意味着 SOAP 堆栈之间必然存在 HTTP 互操作性问题。
HTTP 互操作性问题的一个简单示例就是 SOAPAction 的使用。SOAPAction 是一种 HTTP 标头,它必须存在于通过 HTTP
传送的 SOAP 消息中。此标头可以赋以多个不同的值,例如:
SOAPAction: "http://tempuri.org/"
SOAPAction 的值虽然可以完全为空,但必须用引号引起来:
SOAPAction:
问题就在这儿:如果服务器要求空值 SOAPAction,有些客户端将无法满足这一要求,因为并非所有 HTTP 客户端 API 都
具有设置空 HTTP 标头值的方法。这种问题可能存在两种解决方法:修正客户端 API 和/或确保服务器不要求空值
SOAPAction。通常,避免这类问题的唯一方法是确保所使用的 HTTP API 稳定强壮,并且已知可以在 Web 上工作。即便如
此,这类问题仍可能出现;要彻底消除它们,测试可能是唯一的方法。
XML 问题
这是可能存在的第二类互操作性问题,它们涉及到 XML 语法分析和 XSD 架构处理。SOAP 使用 XML 和 XML 架构作为核
心,因此这两者的互操作性是 SOAP 互操作性的基础。
有一个有趣的互操作性问题示例,它同时涉及到 XML 语法分析和 HTTP 传输,并且与字节顺序标记 (Byte Order Mark,
BOM) 相关。当通过 HTTP 发送数据时,您可以在 Content-Type 标头中指定数据的编码形式,如 UTF-16 或 UTF-8。也可
以通过插入一组用来指定编码形式的字节来表示某一段 XML 的编码形式。当发送 UTF-16 时,即使 Content-Type 标头中
指定了编码形式,也仍需要 BOM 来指示是 big-endian 还是 little-endian;但对于 UTF-8,BOM 则是不必要的。例如:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
n++<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://soapinterop.org/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:echoStringResponse>
<Return>string</Return>
</tns:echoStringResponse>
</soap:Body>
</soap:Envelope>
示例中的前三个字符是字节顺序标记的十六进制代码,用于指示编码形式为 UTF-8,不过,您可以看到,Content-Type 也
指出了这点。即使不需要,但是有些实现方案仍会为 UTF-8 发送 BOM。而其它实现方案有了 BOM 反而无法处理 XML。为
了解决这一问题,应避免在不需要的时候发送 BOM,并且应正确处理 BOM。由于在处理 UTF-16 消息时需要 BOM,所以在
这种情况下务必要正确处理 BOM。虽然没有任何单一的方法可以提早解决这些问题,不过当发现问题时,最好的方法就是
参考描述标准的具体规范(通常在 W3C 上可以找到),然后应用这些规范来评判遇到的问题。
SOAP 问题
现在,我们将讨论问题的核心:SOAP 问题本身。如上所述,SOAP 的互操作性首先要求解决传输(通常是 HTTP)和 XML
问题。解决这两个问题之后,再来解决 SOAP 问题。
SOAP 本身的问题相对简单。它要求将消息装入信封,并将消息的实际内容放在正文元素中。SOAP 使标头等元素成为可选
项,对正文元素中可包含的内容允许存在一定的灵活性。以下是一个简单的 SOAP 消息示例,大多数堆栈与它进行互操作
时不会存在问题:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body >
<foo />
</soap:Body>
</soap:Envelope>
虽然这个示例不是十分有趣,但是 SOAP 还提供一种对常见数据类型进行编码的方法(请参见 SOAP 规范的第 5 节),它
进一步说明了如何对 RPC 方法调用进行编码。您可能已注意到,在前面的示例中,方法名是正文的子标记,参数则是方法
名的子标记。
即使不用这么麻烦,您也可以找到许多有趣的互操作性问题。例如,SOAP 规范规定,如果您收到 mustUnderstand 属性设
置为“1”的 SOAP 标头,就必须理解它,否则将出错。但许多实现方案并没有做到这点。以下是 mustUnderstand 标头的
示例:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
n++<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://soapinterop.org/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<Foo SOAP-ENV:mustUnderstand="1">
Hello!
</Foo>
</SOAP-ENV:Header>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:echoStringResponse>
<Return>string</Return>
</tns:echoStringResponse>
</soap:Body>
</soap:Envelope>
这个示例是通过 SOAP 互操作性测试发现的众多问题之一。有关现已发现的互操作性问题的更多示例,请参见
http://groups.yahoo.com/group/soapbuilders(英文)中的档案。总之,为了确保 SOAP 在实现 RPC 形式通信时的互操
作性,全世界的 SOAP 构建者已经做了很多工作,并取得了丰硕的成果。从 5 月 8 日到 5 月 10 日,在拉斯维加斯将举
行 Networld+Interop 会议,到时,SOAP 团体的许多成员将在会上将充分展示这方面的成果。如果您在使用 SOAP 堆栈或
对其感兴趣,欢迎惠顾这次演示会。
另外,有关 XML Web 服务的许多讨论和测试已经在 http://groups.yahoo.com/group/soapbuilders(英文)、
http://www.mssoapinterop.org/(英文)和 http://www.xmethods.net/ilab/(英文)等站点上进行。这些站点包含到许
多互操作性测试端点的链接。构建 SOAP 堆栈的所有人员都应该阅读这些档案并参与互操作性测试。
后续话题
本文简要概括了在 XML Web 服务领域中发现的一些早期互操作性问题。不过,这方面的讨论并不会就此停止。除了通过
HTTP 进行 RPC 调用之外,SOAP 还有许多更为有趣的情况需要讨论。其中包括“document”形式的消息传递、基于 SMTP
和其它传输机制的 SOAP、WSDL 以及各种 SOAP 标头测试 - 所有这些都值得在今后的文章中进行讨论。
……