2002-08-26 17:08
将旧应用改造成Web服务
Dietmar Kuebler(dkuebler@de.ibm.com),高级软件工程师,IBM
德国
Wolfgang Eibach(eibachw@de.ibm.com),高级软件架构设计师,IBM 德国
2002 年 1 月
随着动态电子商务及其基于开放标准的支持技术的出现,支持企业中的基本业务流程的有价值的旧应用将能够加入到分布式计算的这一新领域中来。在这篇论文中,我们将概略论述如何使Web
服务技术能够应用于旧的应用 ,然后用一个示例来说明概念体系结构在旧应用中的使用。
介绍
Web
服务是电子商务发展的下一个阶段。Web 服务把一切都看作服务,这种服务可以通过在网络上使用消息传递动态地被发现和组织。企业可以通过发布自己的 Web
服务来动态地出售它们的服务。
Web 服务体系结构(Web services architecture(WSA))是将企业旧应用集成到这一新领域的理想技术。这是为了启用程序对程序通信而创建与企业应用交互的、基于 Web 浏览器的用户界面的下一个步骤。这暗示着人们可以以一种更加自动化的方式和更有效的办法来做相同的事情。
自电子交易出现以来,人们已经开发了大量的应用来满足日益增长的对在线购物系统的需求。这些系统大多使用专有实现,通常是因为在进行开发的时候缺乏开放标准。不过,这些早期的专有应用所支持的业务流程在将来仍然是必需的。这可以从人们对这些电子商务应用已作的大量投资中得到证实。
这些旧应用比乍一想起来要更复杂。例如,增值税(value added tax(VAT))计算 — 类似于美国的销售税计算 — 如果要支持带有所有不得不处理的不同条件的全球贸易情况,那么就会变得复杂得多。
为了将旧应用融合到动态电子商务中,我们就需要应用 Web 服务技术,它将允许对服务进行定义,从而隐藏旧应用接口的一些复杂性。
一旦对旧应用做了技术上的改造,业务流程的自动化程度就可能变得更高,也更少需要人工干预。
让旧应用重焕活力
Web 服务的概念和面向服务体系结构(service
oriented architecture(SOA))方法为旧应用在 Web
上可用创造了机会。在这篇文章中,我们将展示如何将概念体系结构应用到当今的众多旧应用中,这些旧应用在大型机和其它服务器上运行。这包括在大型机事务管理器(即
Customer Information Control System Transaction Server(CICS TS)或 Information
Management System(IMS))控制之下的应用。(请参阅参考资料。)
这种概念有许多优点:
它能够使已认证的产品级应用作为 Web 服务可用。这允许为 Web 服务提供者的客户快速部署稳定的 Web
服务。
Web
服务的用户在大型旧应用上的巨额投资将得到保护,同时未被修改的旧应用仍然可以作为服务器应用在大型机主机上运行。
它能够给 Web
用户带来运行基于大型机的应用的优点,例如:
高可扩展性:当一个 Web 服务被启动时,使用该服务的潜在用户的数量是未知的。基于大型机(如
zSeries Parallel Sysplex)群集的服务由 Workload
Manager(WLM)动态管理,并且可以伸缩到非常高的程度。(请参阅参考资料。)
高可用性:Web
服务对于企业对消费者(business-to-consumer(B2C))和企业对企业(business-to-business(B2B))的用户必须是全年全周全天候
99.99%
可用的。大型机群集可被设置成无单点失效,以确保这个级别的可用性。
持续运转:大型机可以在不中断在群集上运行的应用的情况下进行计划内的系统停机,以进行软件或硬件升级。不必中断运转即可引入另外的系统。
概念体系结构
我们的论文将首先展示一个概念体系结构,可以把这个体系结构当作一个模板,用来把已经投入生产的旧应用改造成作为
Web 服务可用的。图 1 显示了这个体系结构的结构,下面的描述将详细解释其中的各个组件。
在这篇论文的后面,我们将展示这一概念的一个实际实现的示例。
图 1:通过 SOAP 访问旧应用的概念体系结构
图 1 所示的概念体系结构包括了一个 Web 服务的三个组件:服务提供者、服务请求者和服务中介者。服务请求者是 Web
服务的消费者,很可能是运行在企业客户的服务器上的一个程序。服务提供者程序从 UDDI 库即服务中介者处获取关于可用服务的信息。可用的 Web 服务是用 Web
服务描述语言(Web Services Description Language(WSDL))描述的,从而支持与平台无关的通信。
当服务请求者选择了一个服务时,它将使用 WSDL 描述来找出访问该服务的方法。访问该服务的方法一被找到,WSDL 描述便被用来生成发送给应用服务器的 SOAP 请求消息,应用服务器扮演服务提供者的角色。
在上述的示例中,SOAP 请求被作为一条 HTTP POST 请求发出。使用 HTTP 具有能够穿过 Web 服务器上通常都存在的防火墙的优点。如果要求比 HTTP 所提供的消息传递更可靠的消息传递,则您可以使用一个可靠的消息队列系统,例如:MQSeries Internet Passthrough(MQ IPT)或 Oracle 应用服务器。MQ IPT 也在 HTTP 协议上运行,因此能够穿过防火墙(请参阅参考资料)。不过,它也具有 MQ 消息传递给应用带来的所有优点。
穿过防火墙后的 SOAP 请求消息由 HTTP 服务器处理。HTTP 服务器分析 HTTP 头信息并找到 SOAP 路由器组件的名称,该名称是统一资源名(Uniform Resource Name(URN))的一部分。请求消息被传递到指定的 SOAP 路由器。SOAP 路由器分析 HTTP 头并找到某个 Web 服务适配器(Web service adapter)的位置。然后,SOAP 路由器将把该请求传递到所请求的适配器。
Web 服务适配器
为了能够使 Web
服务适配器可用于服务访问,必须为每一个服务开发 Web 服务适配器。Web 服务适配器通常是一个连接到后端服务器的 Java
应用程序。这个连接可以是后端服务器支持的任何通信连接,也就是说,它可以是运行在传输控制协议/网际协议(Transmission Control
Protocol/Internet Protocol(TCP/IP))或高级程序对程序通信(Advanced Program to Program
Communication(APPC))协议连接的本机 MQSeries 通道。连接到后端系统的其它选择是使用 CICS TS 外部调用接口(External
Call Interface(ECI)),如果后端系统使用的是 CICS TS 事务系统的话。
对于每个 SOAP 服务请求,Web 服务适配器调用一个后端应用。在一个 SOAP 请求会导致对一个或多个后端服务器系统的多个请求的情况下,生成复杂的 Web 服务也是可能的。后端请求的组合结果被合并成一个 SOAP 响应,这个 SOAP 响应接着被回传给服务请求者。
Web 服务适配器隐藏了调用后端函数的复杂性,只要求您指定执行一个服务时所绝对必需的参数子集。
事务管理
一个复杂的业务组件包含多个需要被执行事务。这些事务请求可能向一个或多个后端系统发出。这其中有一个重要的业务要求就是,所有这些后端请求都必须属于一个称为逻辑工作单元(logical
unit of work(LUW))的主事务。
LUW 必须符合为事务系统定义的要求,这些要求通常称为 ACID 范例:
A 表示原子性(atomicity):事务是处理过程的原子单元;事务或者整个被执行,或者根本不被执行。
C
表示一致性(conistency):LUW 的一个正确执行必须将所涉及的所有资源从这个一致状态变成另一个一致状态。
I
表示孤立性(isolation):在 LUW 被提交之前,在 LUW 中所做的所有更新都不应被其它事务看见。
D
表示持续性(durability):一旦在 LUW
中所做的更新被提交后,这些更改必须永远不会因后来发生的故障而丢失。
最后,回滚也被看作是一个重要属性,回滚能够撤销所有先前所执行的调用。
可以在分布式系统的不同位置控制 LUW 的执行。一种可能是把控制放在客户机位置,客户机在 Web 服务体系结构中就是服务请求者。这在现今是一个问题,因为通过网际连接来控制 LUW 还没有解决方案。在本篇论文给出的所提议的概念体系结构中,LUW 的控制位于 Web 服务适配器。这个解决方案使用了企业 JavaBean(Enterprise JavaBeans(EJB))的事务控制扩展,并且使用后端系统事务管理器来控制对属于这些系统的资源所做的改动。
图 2 显示了前述概念体系结构的一个变体,这个变体使用了 Java 2 企业版(Java 2 Enterprise Edition(J2EE))和企业 JavaBean(Enterprise JavaBeans(EJB))。此外,在后端服务器上添加了一个事务资源管理器。典型的大型机后端服务器事务管理器是 CICS TS 系统或 IMS。
图 2:使用 Web 服务将事务组合成一个逻辑工作单元
通过利用 EJB
的事务协同功能,可以将对一个或多个后端服务器上的事务的许多单个请求的控制组合成一个逻辑工作单元。
如果 Web 服务适配器作为 EJB 会话 bean 实现,则当它接收到对复杂服务的 SOAP 请求时,就将启动一个工作单元。接着,后端系统上的事务通过发送中间件消息被调用。这些消息将被发出到一个或多个后端系统。如果有任何一个来自被调用的后端事务的响应以错误结束,那么会话 JavaBean 将对在不同系统上启动了的所有事务发起回滚。这保证了 SOAP 服务请求或者得到完全执行,或者保持该请求被发出之前的状态。这避免了后端旧系统的数据库的任何不一致状态。
一个样本实现
为了验证这里所描述的体系结构,我们开发了一个样本实现。它使用现有的在 IMS
事务管理器下运行的后端主机应用。这个系统通过专有接口为订户提供各种现今已有的服务。
作为一个示例,我们将欧洲所使用的 VAT 计算实现为一个服务。这个实现使用位于主机位置端的 SOAP 服务器。SOAP 客户机通过应用服务访问该服务,在这个例子中是通过在 Windows 2000 上运行的 WebSphere Application Server 来访问服务。客户机和主机“访问”层之间的通信使用启用了 SOAP 的 MQSeries,并且使用 HTTP 作为底层传输机制。为了让消息能够穿过主机防火墙,就需要 MQ IPT 包。图 3 显示启用了 SOAP 的 VAT 服务的样本实现的概略图。
图 3:启用了SOAP的旧应用样本
用 WSDL 写的 VAT SOAP 服务接口
<?xml
version="1.0" encoding="UTF-8"?>
<definitions name="VatSOAPService-interface"
targetNamespace=
"http://www.boeblingen.de.ibm.com/webservices/vat/vatsoapservice-interface"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://www.boeblingen.de.ibm.com/webservices/vat/vatsoapservice"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<message name="IndoSimpleCalculationRequest">
<part name="city" type="xsd:string"/>
<part name="zipCode" type="xsd:string"/>
<part name="county" type="xsd:string"/>
<part name="state" type="xsd:string"/>
<part name="country" type="xsd:string"/>
<part name="currency" type="xsd:string"/>
<part name="amountExponent" type="xsd:int"/>
<part name="quantity" type="xsd:int"/>
<part name="unitPrice" type="xsd:long"/>
<part name="vatClass" type="xsd:string"/>
</message>
<message name="OutdoSimpleCalculationResponse">
<part name="return" type="xsd:long"/>
</message>
<message name="IndoComplexCalculationRequest">
<part name="city" type="xsd:string"/>
<part name="zipCode" type="xsd:string"/>
<part name="county" type="xsd:string"/>
<part name="state" type="xsd:string"/>
<part name="country" type="xsd:string"/>
<part name="currency" type="xsd:string"/>
<part name="amountExponent" type="xsd:int"/>
<part name="vssis" type="ArrayOfItems"/>
</message>
<message name="OutdoComplexCalculationResponse">
<part name="return" type="ArrayOfVatSOAPServiceItem"/>
</message>
<types>
<xsd:schema targetNamespace="urn:webservices-vat-service"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<xsd:complexType name="item">
<xsd:element name="quantity" type="xsd:int"/>
<xsd:element name="unitPrice" type="xsd:long"/>
<xsd:element name="net" type="xsd:long"/>
<xsd:element name="gross" type="xsd:long"/>
<xsd:element name="vatTaxAmount" type="xsd:long"/>
<xsd:element name="vatTaxPercent" type="xsd:long"/>
<xsd:element name="vatClass" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="ArrayOfItems">
<xsd:complexContent mixed="false">
<xsd:restriction base="soapenc:Array">
<xsd:attribute n1:arrayType="item[]" ref="soapenc:arrayType" xmlns:n1
="http://schemas.xmlsoap.org/wsdl/" />
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
</types>
<portType name="VatSOAPService">
<operation name="doSimpleCalculation">
<input message="IndoSimpleCalculationRequest"/>
<output message="OutdoSimpleCalculationResponse"/>
</operation>
<operation name="doComplexCalculation">
<input message="IndoComplexCalculationRequest"/>
<output message="OutdoComplexCalculationResponse"/>
</operation>
</portType>
<binding name="VatSOAPServiceBinding" type="VatSOAPService">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="doSimpleCalculation">
<soap:operation soapAction="urn:webservices-vat-service"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:webservices-vat-service"
use="encoded"/>
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:webservices-vat-service" use="encoded"/>
</output>
</operation>
<operation name="doComplexCalculation">
<soap:operation soapAction="urn:webservices-vat-service"/>
<input>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:webservices-vat-service"
use="encoded"/>
</input>
<output>
<soap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:webservices-vat-service"
use="encoded"/>
</output>
</operation>
</binding>
</definitions>
结束语
在应用开发上投资始终是企业的一个话题。当开放标准网络化世界开始主宰 IT
世界时,对这些投资的保护可能要发生变化。今天,许多企业都在设法将它们的旧应用改造成面向组件的系统。便于这种改造的一个新的选择可能是 Web
服务技术的使用。旧应用中的基本服务可以包装成 Web 服务并组织成为具有更高价值的服务。
在这篇文章中,我们描述了如何通过应用 Web 服务技术来使旧应用成熟起来。我们已经展示了怎样能够将专有接口改造成动态电子商务所需的基于开放标准的接口。
作为一个示例,我们已经用一个使用来自电子交易领域的旧应用碰到的“实际”问题展示了如何完成这项工作。电子化市场的供应商或类似的企业需要特别用于付费和记帐目的的基本服务。它们也需要由大型机主机服务器提供的稳定性、可扩展性和高可用性。我们也描述了如何可以不修改旧应用所使用的现有系统而对事务管理进行处理。
关于作者 Kuebler 是在 IBM Boeblingen Lab 工作的高级软件工程师。自 1990 年进入 IBM 以来,他担任过开发、技术营销和项目管理等各种职务,具有在多环境下进行体系结构和软件开发的广泛经验。他的专业技术领域包括面向对象技术、VisualAge for Java、WebSphere 以及中间件技术。他目前的职责包括用于动态电子商务的电子公共设施(eUtility)的定义、体系结构和原型建立。他在德国 Stuttgart University 学习计算机科学,毕业于 1990 年。您可以通过 dkuebler@de.ibm.com 与他联系。 |
|