2002-08-27 10:55
理解Web服务互操作性
--集成多供应商Web服务实现的问题
Frank Cohen (fcohen@pushtotest.com)
总裁,PushToTest
2002 年 2 月
Web
服务技术许诺使软件应用程序之间的互操作性达到新的级别。那么,平台供应商、软件开发者及实用程序供应商争先恐后的给他们的软件加上 SOAP、WSDL 和 UDDI
功能也就不足为奇了。在这篇文章里,Frank Cohen 描述了 Web 服务实现的不一致性以及如何评估 SOAP
技术以更快的交付更好的软件。
噢,美丽的新世界
一踏上这个新的 Web
服务之岛,人们也许会想:“噢,美丽的新世界拥有这样的奇迹!”于是,Web
服务的实现就在眼前。许多平台供应商、独立软件供应商以及实用程序软件开发者们都已经在各自的产品中实现了 Web 服务协议(SOAP、WSDL 和
UDDI)。尽管这些协议现在已经将近两年了,下一个规范(例如 SOAP
1.2)的工作草案也在起草当中,但是开发者们必须就规范的某些部分解释其含义。解释使互操作性问题渗透到了基于 SOAP 的 Web 服务中。
Web 服务互操作性的目的是提供从一个软件应用程序到另外一个软件应用程序无缝的、自动的连接。SOAP、WSDL 和 UDDI 协议定义了一种自描述的方式发现并调用软件应用程序中的方法 - 不必考虑位置或平台。数据被编入 XML 请求和响应文档,并使用 HTTP 或基于消息的协议在软件包之间移动数据。互操作性问题就潜伏在发现、定义以及请求/响应机制中。
发现
在 Web
服务乌托邦的梦想世界里,每个软件应用程序都以自发现和自分类方法被编码。缺少需要的功能的软件查询基于 UDDI 的服务注册中心,并自动同找到的 Web
服务达成协议处理这一任务。一找到 Web 服务功能,WSDL 和 SOAP 就可以通信了。然后的问题就是将该功能所做的事分类,以使其可以被发现。UDDI 定义了
TModel,它就是描述功能的位置、路径和特性的分类法。
UDDI 使企业可以托管可用 Web 服务的在线注册中心。Microsoft、HP 和 IBM 已经开始在公共的因特网上向企业提供 UDDI 注册中心。企业使用 UDDI TModel 系统将被托管的 Web 服务分类。而问题正在于此:UDDI 允许有多种分类法并期望自己管理注册中心里的错误条目。例如,假设有一个打印并发送发票的 Web 服务用 SIC 代码把自己列入一个 UDDI 注册中心,但没有列出地理信息。在地球的另一端使用这样的 Web 服务是可行的。但是,自己去寄信可能更简便。
最终 UDDI 将会被传统分类法的提供者们很好的采用及理解,这些分类法包括 LCSH(美国国会图书馆主题标引,Library of Congress Subject Heading)、FAST (Faceted LCSH)、DDC(杜威十进分类法,Dewey Decimal Classification)以及 LCC(美国国会图书馆图书分类法,Library of Congress Classification)。到分类法专家增长了他们开发和维护 UDDI 目录结构的实践知识为止,请为互操作性问题作一些规划。
定义
Web 服务用 WSDL 来定义如何请求基于 SOAP 的方法。WSDL
假设多个公司合作定义定制数据类型。由协作组织测试这样的合作,这些协作组织正在建立互操作性测试套件。例如,SOAPBuilder 是 SOAP
开发者的一个开放组织,这个组织定义互操作性测试套件来检查 SOAP 定制数据类型的兼容性。现今出现的测试套件从 SOAP 接口的 WSDL
定义开始。他们测试请求和响应文档的内容的有效数据。
这是继 WSDL 成果之后的补充的能量。诸如 Cape Clear CapeStudio 和 BEA Cajun 的新技术自动为基于 SOAP 的 Web 服务开发 WSDL 文档。诸如此类的工具消除了在开发者手工编写 WSDL 文档时出现的构造拙劣的 WSDL。
清单 1:自动生成的 WSDL 文档
<?xml version="1.0" ?>
<definitions
name="PushToTestService"
targetNamespace="http://www.pushtotest.com/pushtotestservice.wsdl">
<message name="testRequest">
<part
name="userName" type="xsd:string" />
<part
name="authenticationToken" type="xsd:string" />
<part
name="goodUnitl" type="xsd:Date" />
</message>
. .
.
人们认为是 WSDL 文档导致了互操作性问题。例如,考虑一下上面的软件测试 Web 服务的 WSDL 文档片断。WSDL 定义了如何发送 testRequest 命令。但 <definitions> 元素没有定义名称空间。正确的 <definitions> 元素应当看起来如清单 2 所示的样子。
清单 2:<definition> 元素的正确使用
<definitions xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s0="http://tempuri.org/"
targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/">
开发者可能会认为 Web 服务默认使用标准 W3C SOAP 名称空间。尽管这对基本数据类型(如 String)可能是可行的,对于将会在本文后面的内容中出现的 Date 数据类型会有已知的互操作性问题。不指定名称空间,Web 服务就可能无法正确的处理数据类型。
请求/响应
SOAP
定义了软件应用程序相互调用方法和传递数据的标准方式。SOAP 请求是 XML 文档,这些文档含有对名称空间、被调用方法以及数据的描述。XML
试图使开发者们可以相当灵活的编写 XML 元素和定义。这样的灵活性对 SOAP 互操作性而言是一个问题。
例如,一个典型的 SOAP 响应文档看起来可能会如清单 3 这样。
清单 3:一个典型的 SOAP 响应
<?xml version="1.0"
encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:echoStringResponse
xmlns:ns1="http://soapinterop.org/">
<result
xsi:type="xsd:string">Hello!</result>
</ns1:echoStringResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
这个响应文档正在发回一个包含文本“Hello!”的 String。<result> 元素还包括 xsi:type="xsd:string" 参数,这个参数被反序列化成一个 Java 的 String 对象。许多 SOAP 工具在请求和响应文档中加入了显式类型定义信息。另一方面,一些 SOAP 库返回无类型信息的响应。
清单 4:无类型信息的另一个 SOAP 响应
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/">
<result>Hello, I'm a string!</result>
</ns1:echoStringResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
上面的响应文档中的 <result> 元素没有包含类型信息。这样,反序列化 <result> 值的 SOAP 库必须查看服务的 WSDL 描述来找出返回类型的描述。如果 WSDL 没有定义响应类型,那么返回的将是哪种类型的对象就没有确定答案了。
数据类型
数据类型在 Web 服务中就如同轮胎与路面的关系
-“一拍即合”。SOAP 使用序列化器和反序列化器对象把软件应用程序的本机语言翻译成通过网络传输请求的 SOAP
协议。在此,本机语言引入了对数据的依赖。例如,Java 定义日期对象的方式同 Microsoft .NET C++
定义日期对象的方式并不相同。这将带来允许同名的 SOAP 数据类型具有不同的实现的不良后果。互操作性问题来了。
不能通过互操作性测试的最常见的数据类型是浮点数和日期。
浮点数和十进制数据类型
浮点数在 SOAP 中被表示成十进制数字字符串。浮点数的
SOAP 定义还使工程师长时间使用的标记法来表示指数成为可能。一般情况下,这种方法会如您所愿。但是,浮点数在被推入时会遇到问题。
例如,最初的 IBM SOAP4J 实现(现在是 Apache SOAP 和 Apache AXIS 库)使用 Java 的 toString 方法以及构造函数把 SOAP 文档中找到的浮点值转换成 Java 对象。数字作为一串十进制数字出现。当涉及序列化浮点数“无穷大(infinity)”时,Java 输出“Infinity”这个字符串。另一方面,XML Schema 把无穷大序列化为“INF”。这导致了 SOAP4J 和其它 SOAP 工具箱之间的互操作性问题。
正如因特网产生于网络管理员们的合作一样,现在我们看到 SOAP 的实现者们正同心协力解决互操作性问题。前身是 SOAP4J 的 Apache SOAP 被改为接受“INF”作为序列化无穷大的一种有效方式。
十进制数据类型在被推入时也会受到语言依赖的影响。十进制数据类型可以表示达 40 位精度的大数。除非服务器端和客户机端是在相同的语言上实现的,否则依赖 SOAP 请求或响应中的所有 40 位会有问题。对于日期的秒的小数部分和小数位上的尾零也是如此。
语言依赖性引入的互操作性隐患的一个很好的示例就是 BigDecimal。十进制数字是银行应用程序的金融计算的一个必要部分,银行应用程序里会需要很大的数字。十进制数据类型的 XML Schema 规范允许任意精度。十进制数据类型可以表示 1000 位精度,也就是说,一个被表示成 1000 个一位数字的字符串的十进制数。Apache SOAP 是基于 BigDecimal 数据类型的 Java 实现。根据底层操作系统(Solaris、Windows 等),Java 的 BigDecimal 有一个数字精度的上限。
XML Schema 对这些类别的互操作性问题的解决办法是定义最低限度满足要求的实现规范。就十进制数据类型而言,XML Schema 要求至少要有 18 位精度。Apache 和 Java 满足这一要求。但是,这并不意味着基于 SOAP 的 Web 服务会接受这样的最低精度。
Microsoft .NET 实现处理 BigDecimal 数据类型达 29 位精度。那么带 BigDecimal 数据类型的 Apache SOAP 请求接收到一个 .NET 响应时,多出来的那些位精度会怎么样呢?不幸的是,答案要取决于本机 SOAP 序列化器和反序列化器实现。而且问题在于,SOAP 事务是有效的但数据是错误的。开发者们必须精于把数据测试和保护编进他们的软件应用程序中才能照顾到 SOAP 交换带来的无效数据。
Date
数据类型
互操作性问题对日期数据类型的影响程度要甚于浮点小数数据类型。XML Schema 定义 dateTime
数据类型包含世纪、年、月、日、小时、分钟和秒。但是,毫秒、微秒甚至更小的时间度量单位呢?我们生活在一个 1.1 GHz Intel CPU 卖不到 $150
的世界里,用户要求 Web 服务执行最多只要 2-3 秒钟。在几乎所有的 Web 服务性能的度量标准中,毫秒都要计算在内。
XML Schema 规定秒之后的任意个数位可以被编码成 dateTime 数据类型,但是并没有规定应用程序必须支持的数位的最小数目。Apache SOAP 使用 Java Date 类(java.util.Date)来序列化和反序列化 dateTime 数据类型。Java Date 支持几乎接近毫秒的精度。.NET 的 Date 数据类型使用达 4 位精度的亚秒值,所以纳秒可以用 .NET Date 数据类型来表示。
前景
现在的 Web 服务是由核心 UDDI、WSDL 和 SOAP
协议提供的。定义工作流自动化、Web 服务管理服务以及垂直营销协议的另一层协议即将出现。Web
服务对开发者们构建高度集成的解决方案很有帮助。因此,在工作流自动化 Web 服务同垂直营销 Web
服务结合时看到互操作性问题的到来并非意料之外的事。
如果 Web 服务工具箱得到持续的改进以解决互操作性问题,那么顾客、用户和企业将比使用现有的标准(CORBA、DCOM 和 RMI)更高效的解决系统集成问题。比较认真的 Web 服务工具箱供应商一直在努力解决互操作性问题。如果互操作性问题被搁浅或者加剧,那么要实现集成系统,我们就不可避免的要花费更多的专业服务且更迟的考虑采纳 Web 服务。
同时,Web 服务即将以几乎普遍的采用作为很好的开端。真正的互操作性难题可能会是在 SOAP 和非 SOAP 方法需要通信的领域,如 IIOP 上的 CORBA。