内容


面向服务的架构中的策略支持

Comments

引言

面向服务的架构(SOA)引入了一个高度分布的体系结构,在这个体系结构中,多个不同的客户在调用同样的服务。在此分布式系统中,不同的客户对于同一服务的调用具有不同的服务质量要求(QoS)。另外,新版本的服务经常被引入,这就要求将不同客户对于特定服务版本的请求进行正确路由。所有这些服务请求都可以归结描述为服务调用策略。这些策略可以单独管理或整合到服务的定义之中。

服务调用策略类型

服务调用主要有以下几种类型:

  • 版本支持策略: 同样的服务(方法)在整个系统中可能会有多个版本。版本支持策略定义了对于特定的服务调用将会调用哪个版本的服务(方法)。
  • 服务质量支持策略:同一服务的不同客户对于服务调用可能需要不同服务级别协定(SLA),包括性能、事务支持和安全需求等等。服务质量支持策略定义了服务调用所支持的 SLA。
  • 有效负载支持策略:服务可能需要客户通过特定的方式对有效负载进行编码。如 UTF-8、英语等等。有效负载支持策略定义了服务的编码需求。

版本策略

一旦创建和部署完毕,服务(包括服务的方法)在它们的整个生命周期过程中都会发生变化。在此过程中,服务方法的实现和契约(contract)都会发生变化。这种变化将会影响到特定服务的部分或全部客户。由于潜在的数量巨大的服务客户,因此一旦服务发生变化,就将它们全部升级将是不现实的,这通常导致对于 SOA 产生新的需求,要求 SOA 支持多个版本的服务并行运行。

在这种实现方法中,可以看到服务本身(服务名称)没有发生变化。换句话说,服务方法可以增加、移除或者版本升级。理论上讲,只要服务方法的协议没有发生变化,就没有必要创建新版本的方法,服务的现有方法的客户将不会感觉到任何改变。这从根本上简化了整个服务版本的进化。在这种方法中:

  • 如果现有契约的一个新的实现被引入,那么客户将不会受到影响,也不需要新的版本。
  • 如果一个新的契约被引入,那么现有的服务将创建一个新的方法。
  • 现有服务的方法可以被弃用(类似与 Java 技术中的方法弃用)并最终被移除。

然而在现实中,这一简单的方法并不总是可行的,因为:

  • 尽管底层实现发生改变并没有影响到契约,但通常服务客户不愿承担使用一个未经过完整测试的新方法所带来的风险。这就需要创建新版本的方法。
  • 尽管方法的契约发生改变,但这种变化是无关紧要的(这种情形对于重要性没有明确定义),这时创建一个方法的新版本要比创建一个新的方法更合适。

QoS 策略

QoS 策略定义了所需服务质量的组合,包括 SLA 级别、安全、事务需求以及其它因素。安全 QoS 定义了服务调用是否需要支持安全以及明确的安全实现。事务支持定义了调用是否是事务性的,如果是的话,是什么事务类型(原子性的(两阶段提交)还是商业事务,或是其它)。

服务调用 SLA 支持是个非常复杂的话题,已超出了本文的范围。但是可以对服务客户定义一个全局 SLA 类型(例如,白金级别、黄金级别等等)。这种 SLA 类型通常用来定义特定服务客户的重要性。对于 SLA 策略我在这里仅考虑这一点。

编码策略

服务方法的有效负载,用 XML 表示,实际上是包含 XML 文档的字符串。字符串可以有不同的编码(如,ASCII、EBCDIC、UTF-8 等等),并且字符串的内容可以采用不同的语言。消息本身的实际编码方式(信封)通常是 SOAP,但同时也支持其它编码。为了实现服务客户和服务提供者能够成功交互,二者需要对以上参数达成一致。实现服务客户和服务提供者之间在上述问题上相互一致的一个方法就是公布服务提供者的编码策略并保证客户能够访问到它。这种方法的一个扩展就是使得服务提供者支持几种不同的编码策略,而客户可以从中选择一个合适的编码策略。

策略支持方法

实现上述策略支持的最简单的方法就是多次部署同样的服务或服务方法,每个版本对应一个特定的策略。在这种情况下,每一次部署公开一个或多个端点(访问服务的机制),每一个端点对应于特定的策略(策略集)。完成这些之后,服务的标准定义可以被扩展为多个端点之上策略支持。这一定义可以作为对于特定端点的服务请求路由的基础,而不管真正的路由是如何实现的。

服务定义

图 1 展示了信息的整体架构,它用来满足基于策略的服务请求路由:

图 1:服务定义
服务定义
服务定义

在这里,服务被定义为方法的集合。每个方法都可以有多个并行部署的版本(版本策略)。基于不同的策略(这里的策略指的是 QoS 和编码策略),每一个版本都有多个服务端点。最后,基于客户需要的交互方式(同步或者单向),每个服务端点又具有多个端点地址。

本文提出的服务定义将策略支持分为 3 个不同的层次:版本、QoS、编码和交互。这种层次划分的原因在于试图将它与端点地址选择决策流程结合起来。假设端点地址选择决策流程包含以下步骤:

  • 服务选择
  • 服务方法选择
  • 服务方法版本选择
  • 基于 QoS 的服务端点选择
  • 基于交互方式的端点地址选择

服务定义的标准化

目前定义服务的标准方式是利用 WSDL1.1,由于它不支持所需要的层次( 图 1 ),因此,我和我的同事采用了将下面 3 种新兴的规范组合起来的解决方案:

  • WSDL 2.0 (参阅 参考资料) 代表了 W3C 对于未来 Web 服务定义方法的思考。它明显提高了 WSDL 1.1 在下述方面的能力:
    • 对于特定的操作定义交互模式的能力
    • 定义编码方式的能力(SOAP 还是私有的),以便对目前非 SOAP 实现提供向后兼容支持
    • 对于单个服务定义多个服务端点的能力
    WSDL 2.0 并没有规定如何来定义端点,而是依赖于其它的标准来实现这一点。
  • WS-Addressing (参阅 参考资料) 提供了定义端点的通用方式。这个标准最初提出只是用在 SOAP 消息头的定义,但同时也应用在 WSDL 中用来定义所需的端点。这一标准具有很大的扩展性,允许您定义:
    • 基于定制脚本,任何传输根据特定的应用都可以定义端点。
    • 服务质量需求和基于 WS-Policy 的特定服务端点的支持。

    我们关于实现 WS-Addressing 扩展的源文件和本文一起提供,您可以通过点击本文顶部或底部的 Code 图标来下载。

  • WS-Policy (参阅 参考资料) 提供了定义特定端点的 QoS 和编码需求(策略)的通用方法。这一标准最初提出是供客户定义他们的需求,以及用在 SOAP 消息头中来在请求中定义这些需求,但它同时也用在 WSDL 中来定义特定服务端点的策略。WS-Policy 明确支持下列策略声明:
    • 消息语言
    • 消息方言
    • 消息编码
    • 版本定义
    • 消息安全(基于 WS-Security )

    另外,WS-Policy 可被扩展以支持定制的策略声明。我们关于实现 WS-Policy 扩展的源文件和本文一起提供,您可以通过点击本文顶部或底部的 Code 图标来下载。

基于上述标准和提出的扩展,我们利用如下规则生成了一个示例 WSDL(您可以通过点击本文顶部或底部的 Code 图标来下载):

  • wsdl:definition 定义了整个服务。
  • wsdl:type 定义了服务内所有方法使用的消息。这些消息类型是可选的,在运行时并非强制使用。它们通常被一些工具用来从 XML 编组自动产生程序语言(Java 语言 C#)或根据程序语言生产 XML 编组。 在示例 WSDL 中我们省略了 wsdl:type
  • wsdl:interface 用来定义基本的服务以及服务支持的方法。 wsdl:interfacewsdl:operation 的序列,它定义了每一个特定的方法。 wsdl:operation 用来定义输入、输出和缺省的消息(在我们的示例中没有应用),它同时也定义了特定方法的首选交互方式。
  • wsdl:binding 描述了方法使用的固定的消息格式和传输协议。Binding 可用来定义服务层或方法层。 我们对于服务始终采用单一的绑定。对于每个方法的特定绑定信息在 wsdl:operation 中定义。通过在每个消息内定义 soap:body 元素, wsdl:binding 内的 wsdl:operation 可扩展定义在 wsdl:interface 内的 wsdl:operation。 这一元素可包括消息命名空间和编码方式。 wsdl:operation 内的 soap:binding 元素同样能够定义首选的传输和消息方式 (文档或者 RPC )。 因为我们对每个服务定义了明确的端点,因此在 wsdl:operation 子句中我们不使用这些特性。
  • wsdl:service 描述了服务提供的一组交替的服务端点 。因为 wsdl:service 与契约(整个服务)关联,而不是与服务的方法相关联,我们提出了一个命名转换 ,将每一个 wsdl:service 元素与一个特定版本的服务方法相关联。这意味着 5.1 版本的方法 synchronizeAgreementwsdl:service 元素将有一个名字 synchronizeAgreementServiceV5.1。这种命名转换允许对每一个方法的每一个版本都创建一个 wsdl:service元素。 wsdl:service 元素内的每一个端点通过一组与此端点关联的特定策略来区分。基于客户需要的交互方式,每个端点可以定义多个端点地址。

WSDL 处理

基于客户语言程序的需求:版本和 QoS,为找到适合的服务端点地址,针对服务定义提出的解决方案需要大量的 WSDL 处理。

WSDL 编组和分组方法

对于 WSDL 处理,有如下 3 种基本方法:

  • 基于 DOM 的方法:由于 WSDL 文件从本质上来讲是一个 XML 文件,现有的 DOM API(例如 Xerces)能够用来进行解析或者构建 WSDL 文件。这种方法是最通用的,但同时也是处理 XML 文件最费力的方法。尽管从技术上来讲是可行的,基于 DOM API 的实现对于代码敏感且容易出错。同时,这一解决方法迫使您不得不处理两个完全不同的模型:DOM 和 WSDL 模型。
  • 基于特定 API 的方法: 利用 IBM 的 WSDL4J 来实现 WSDL 操作就是一个例子。这种方法倾向于 WSDL 模型,它允许您直接操作 WSDL 。这种方法的不足在于您不仅要处理 WSDL 本身,还要处理 WS-Addressing、WS-Policy 和扩展脚本。它同时还使用那些尚未成为标准的事物,这就意味着现有的一些 API 将会改变。在撰写本文的同时,一些试验性的 API 支持 WS-Addressing 的当前版本,但对于 WS-Policy 和扩展脚本却根本不支持。这就意味着这种基于特定 API 的方法不得不掺杂一定数量的 DOM 处理。
  • 基于 Java 生成的方法:因为描述我们实现的所有脚本都是标准的 XML 脚本,因此可以生成对应于这些脚本的 Java 类(支持 XML 编组和分组)。在这种情况下, WSDL 文件直接转化为 Java 类,然后作为 Java 对象来管理。考虑到标准在不断进化这一事实,定制性的扩展将是很有必要。由于它的灵活性和对变化的适应性,这一方法最适合实现我们的解决方案。

基于以上分析,我们决定采用基于 Java 生成的方法来处理 WSDL 。目前有好多方法用来从 XML 生成 Java 代码,例如 Castor、 Breeze Studio 和 Eclipse 建模框架 (EMF)。在我们的实现中,我们选择了 EMF (参考 EMF Sidebar) ,因为它最能满足我们的需求:支持多种脚本,支持最新的(被广泛应用在WSDL上的)XML 标准,xsd:any support 等等。它同时(利用可视化工具)还产生了对于模型生成代码的直接连接。我们利用 EMF 2.0 和 XSD 2.0 在 Eclipse 3.0 上生成代码。

抽象层

尽管基于 EMF 的方法允许直接处理 WSDL 文件,但它并不是非常适合直接处理 WSDL 信息。问题是这些产生的 Java 类遵循 WSDL 对象模型(图 2),而不是遵循提出的服务定义模型(图 1)。

图 2:WSDL 对象模型
对象模型
对象模型

为对 WSDL 信息进行串行化的实时处理,并且使我们避开所使用的标准的潜在变化带来的影响,我们创建了一个单独的抽象层来优化搜索,这一点是正确的请求路由所必须的。 图 3 展示了这一抽象层的类图。

图 3:服务定义抽象层
抽象层
抽象层

将它们集成到一起

尽管抽象层( 图 3)和(利用 EMF( 图 2)产生的)WSDL 表示都提供模型描述,但同样的 WSDL 信息在这两种表现方式中是不同,需要一个驱动程序在这两种表现方式间进行转换,如图 4 所示。

图 4:EMF 到抽象层的映射
映射
映射

驱动程序 (参阅 参考资料) 通过集成 EMF 和抽象层的 API 来实现。

使用提出的服务定义

基于提出的扩展服务定义,您可以通过下面两种方式来路由服务请求:

  • 从客户直接路由
  • 基于中介体的路由

从客户直接路由

在这种体系架构中,客户通过客户策略文件进行配置,在定义信息中需要单独定义所需的服务端点。基于这些策略和期望的交互类型,服务调用的一个适合的端点地址将被选择,从而请求将被正确的路由。

图 5:从客户直接路由
直接路由
直接路由

基于中介体的路由

在这种体系架构中,客户从不与服务直接通信,只是通过中介来实现交互。中介发现客户请求后,将获取特定于客户的策略文件。基于这些策略和期望的交互类型,服务调用的一个适合的端点地址将被选择,从而请求将被正确的路由。

图 6 基于中介体的路由
中介体路由
中介体路由

路由方式对比

这两种路由方式各有优缺点。从客户直接路由的方式具有以下优点:

  • 它产生最低的基础设施负荷,特别是在传输 MOM 对象的情况下。
  • 它提供最佳的整体调用性能。

这种方法的缺点包括:

  • 服务实现的标准方法通常假设服务客户具有服务定义文件的静态编译。从客户直接路由的方法相反,期望动态路由,因此需要服务定义文件的动态处理。
  • 依赖于客户实现,改变客户策略文件需要重新编译客户。

基于中介体的路由的方法有以下优点:

  • 它提供了对于所有策略配置的一个中心点,从仓库中获取服务客户并处理信息。
  • 它不需要客户动态绑定-所有的服务调用请求都被路由到中介点。

这种方法的缺点是:

  • 中介体的引入通常需要额外的设备。
  • 由于这种方法需要额外的发送传递,整体性能将会降低。
  • 中介体将成为服务调用的瓶颈和唯一的失败点。
  • 对于系统中的每个服务,中介体需要在每个请求中加入一个入口点,除非存在一个指向适当服务的特定头部入口。

还有许多服务管理解决方案,他们通过引入中介体和代理策略来实现请求路由。

结束语

WSDL 2.0、 WS-Addressing 和 WS-Policy (利用最少数量的定制模式) 的组合允许创建非常灵活的服务定义文件,该组合依次允许支持服务请求(基于非常复杂的服务调用策略)的运行时路由。EMF 产生的代码使得可以直接生成 API ,用来支持 WSDL 文件的编组和解组,以及底层的模型管理。

致谢

作者感谢他在 CNA 和 IBM 的同事,特别是 James Mckune 和 Gerald Daus,正是在他们的帮助下才使得作者完成本文。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=SOA and web services, XML
ArticleID=49258
ArticleTitle=面向服务的架构中的策略支持
publish-date=12012004