下载本文的PDF版本 PDF

审慎的变革

通过 XML Web 服务转型集成

Mike Burner,微软

尽管批评者嘲笑 XML Web 服务是带有臃肿问题的 CORBA,但行业啦啦队却说这些服务正在开创无缝集成计算的新时代。但是对于我们这些工作不涉及制造行业兴奋感的人来说,Web 服务能提供什么呢?

过去十年对互联网基础设施和电信的大量投资,使得曾经不可思议的事情变得完全可以实现。组织现在可以从其规范来源、合作伙伴和客户那里实时检索最新数据。并且,在传统上应用程序将功能绑定在一起的地方,现在可以实际地实时访问应用程序逻辑,从动态更新以跟上不断发展的业务流程的托管服务中访问。

各方现在必须就如何表示信息、检索和更新数据的协议以及证明执行此操作的权限的方法达成一致。这些必要性催生了 XML Web 服务。这些服务的架构试图桥接无数的互联网系统,让从小型企业到跨国企业再到世界各国政府的组织,能够使用数据和流程的程序化接口更有效地进行沟通。

Web 服务已经引起了很多兴奋,供应商们正在争先恐后地将他们的平台描绘成最兼容、最成熟、最安全,或者仅仅是最有可能大量生产精美 T 恤的平台。本文试图深入探讨炒作之下, بررسی XML Web 服务与现有架构的不同之处,以及它们如何帮助构建客户解决方案。让我们首先描述 XML Web 服务的特性,即

Web 服务的承诺

通过使用通用数据类型集合——XSD 数据类型和从 XSD 数据类型构建的复杂类型——XML Web 服务明确地在服务状态的线路表示和用于处理的平台特定数据类型之间转换服务状态。凭借这种平台无关的状态表示,相同的服务契约可以被不同的服务遵守,并且消费者不受服务提供商平台的约束。状态级别的这种互操作性是使用 XML Web 服务实现集成的关键,并显着提高了软件重用的抽象级别。

将应用程序逻辑隐藏在消息接口之后,说明了一个称为松耦合的原则:即组件之间依赖性较小的架构更易于成功。在紧密耦合的架构中,对一个组件的更改可能会产生级联效应,需要更新其他组件才能正常运行;这些架构有时被描述为脆弱的。Web 服务架构强制执行基于契约的接口,该接口定义了服务可以交换的消息。所有实现细节都对调用服务隐藏,因此避免了脆弱性。当然,契约本身也需要演变。在后面的章节中,我们将探讨 Web 服务版本控制。

通过利用 Web 基础设施,XML 创建了一个自描述类型和服务分类法,客户端和服务无论其底层平台如何,都可以寻址和使用该分类法。XML 实现了自描述数据;WSDL 实现了自描述服务;UDDI 实现了可以以编程方式发现和使用的自描述 Web 服务网络。

XML Web 服务承诺为组件间通信提供开放、无处不在的连接,就像 Web 为人与人之间的通信实现的那样。正如任何人都可以发布网页一样,任何人都可以提供 XML Web 服务。正如各种浏览器可以消费和显示 HTML 一样,各种客户端可以理解 Web 服务的 WSDL 契约并消费服务产品。HTTP 和 Web 的巨大成功创造了庞大的技术和人员基础设施,能够大规模交付 Web 服务。数百万计算机专业人员为 Web 开发、扩展 Web 应用程序并全天候运行它们。数亿台设备运行软件以提供或消费基于 Web 的应用程序。并且存在一个庞大的全球网络来路由 Web 流量。支持 Web 服务的基础设施和专业知识已经存在。支持 Web 服务的其他 Web 架构原则包括

社区创新。 就像 Web 本身一样,Web 服务将通过累积效应取得成功。许多人将贡献他们的创造力,使技术堆栈随着每个额外的从业者而变得更好。

联邦制。 Web 服务宇宙建立在互联网的联邦结构之上,允许每个组织定义自己的策略和结构,同时在适当时利用其他组织发布的成果。XML 对命名空间的支持就是一个例子,它消除了对标签名称达成全球协议的需求。组织和个人在唯一的命名空间内建立他们的 XML 模式,该命名空间可以包含全球组织发布的类型定义。

渐进主义。 Web 服务可以逐步采用。它们可以建立在现有基础设施之上,并且可以与其他分布式计算技术协同工作,以最小的承诺产生收益。

微小的泡沫

在未来几年,我们将体验到 Web 服务技术两个关键领域的创新浪潮。第一个将是 XML 模式的定义和发布,作为互联网上组件间通信的通用语言。XML 是正在开发此语言的通用语法。第二个创新将是 SOAP 标头元素的定义,这些元素扩展了 Web 服务消息传递的功能。(从技术上讲,标头元素定义只是模式定义的另一种形式。)

SOAP 标头元素的灵活性为全球通信架构的创新提供了巨大的机会。在本节中,我们将通过开发一组假设的 SOAP 标头来增强虚构的采购服务,从而阐明 Web 服务设计的一些最佳实践。该服务的功能需求将保持简单,以掩盖混乱的现实世界细节。此类服务必须接受包含订单、项目、送货地址和付款工具元素的文档;如果输入文档不完整或不正确,则生成 SOAP Fault;如果订单有效,则生成订单确认文档。

图 1 中描绘的输入消息不需要 Header 元素,因为消息的功能需求可以在消息 Body 中表示。但是,由于开发和部署软件解决方案的大部分精力都集中在安全性、可靠性和可扩展性等问题上,因此让我们解决这些操作需求。此假设解决方案的一个操作需求是,多次接收同一消息不应导致重复订单。由于网络通信本质上是不可靠的,因此重试未确认的消息是很常见的。有时,原始消息和重试都会通过,这可能是由于简单的延迟,也可能是因为第一个确认不知何故丢失了。

图 1

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <thisApp:Order xmlns:thisApp="URI-1">
      <thisApp:Item>
        <partNumber>1234567890</partNumber>
        <Quantity>2</Quantity>
      </thisApp:Item>
      <someStandard:deliveryAddress xmlns:someStandard="URI-2">
        <Name>Jane Doe</Name>
        <Street1>1 Jane Doe Way</Street1>
        <City>Nowhere</City>
        <Province>California</Province>
        <Country>USA</Country>
        <postalCode>00000-0000</postalCode>
      </someStandard:deliveryAddress>
      <anotherStandard:paymentInstrument xmlns:anotherStandard="URI-3">
        <instrumentType>Visa</instrumentType>
        <instrumentID>0000000000000000</instrumentID>
        <instrumentEvidence type="Owner">Jane Doe</instrumentEvidence>
        <instrumentEvidence type="expiryDate">01JAN2004</instrumentEvidence>
      </anotherStandard:paymentInstrument>
    </thisApp:Order>
  </s:Body>
</s:Envelope>

对于没有副作用的请求(例如文档检索请求),无需防止重复处理,但对于逐步影响持久状态的请求,保护措施非常重要。这里有很多场景需要考虑,包括按件收费的读取。这里的一般原则与确保幂等性有关:保证单个消息无论接收一次还是多次都具有相同的效果。SOAP 标头元素可以防止错误地处理重复消息。一种直接的方法可能是在请求中包含客户端生成的全局唯一标识符 (GUID),例如图 2 中所示的标识符,服务器可以存储并检查该标识符。

图 2

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <reliableMessaging:messageIdentifier xmlns:reliableMessaging="URI-4">
      SOME-GUID
    </reliableMessaging:messageIdentifier>
  </s:Header>
  <s:Body>
  ...
  </s:Body>
</s:Envelope>

另一个操作需求可能是提供有保证的交付。在互联网上,可能永远无法完全保证交付,但可以构建基础设施来接近保证交付。与其为每个服务设计近乎完美的可靠性和高度冗余的连接,不如接受 99.9% 的可用性,并通过互联网规模的消息队列服务(具有六个“九”的可用性)进行路由,以防止在您的服务无法访问的每年八小时内消息丢失。为了同时说明几个想法,此解决方案有点复杂。客户端不应依赖于订单处理服务的即时响应,而应将消息推送到队列服务,从该服务接收确认,然后断开连接。一旦流程完成,订单处理服务就可以使用客户端提供的回调端点将订单确认路由回客户端。这种方法称为异步消息传递,是我们稍后将讨论的重要服务设计模式。图 3 表示通过队列服务路由订单的可能 SOAP 标头。

图 3

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <complexRouting:messageRoute xmlns:complexRouting="URI-5">
      <to>http://hypotheticalservice/placeOrder</to>
      <via>http://somequeuingservice/storeAndForward</via>
      <callback>
        <callbackEndpoint>http://clientListener/hypoOrders</callbackEndpoint>
        <callbackReference>SOME-URI</callbackReference>
      </callback>
    </complexRouting:messageRoute>
  </s:Header>
  <s:Body>
  ...
  </s:Body>
</s:Envelope>

客户端将消息传递到队列服务,可能使用 HTTP,并在队列服务将其消息持久化到其队列后接收收据确认。队列服务可能会插入另一个标头元素,指示订单处理服务以数字签名确认接收来响应。当订单处理完成时,订单处理服务将向客户端指定的端点发送消息——订单确认或 SOAP 故障——协议无疑将要求返回 callbackReference 元素,以便订单发起者可以将确认或异常映射到正确的订单。

现在想象一下,我们想让此交易更安全,因为在没有保护的情况下跨网络发送付款信息是不明智的。HTTPS 可能用于传输消息,但沿途的每个中介都必须再次解密和加密消息;这在计算上是昂贵的,更糟糕的是,会将机密数据暴露给中介。一种解决方案是加密正文,以便只有最终目的地才能解密,而标头保持未加密状态以方便处理,如图 4 所示。

图 4

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <security:bodyEncryption xmlns:security="URI-6">
      <Technique>PublicKey</Technique>
      <keyName>假设服务</keyName>
      <Issuer>URI-OF-SOME-KEYISSUER</Issuer>
    </security:bodyEncryption>
    <complexRouting:messageRoute xmlns:complexRouting="URI-5">
      路由内容
    </complexRouting:messageRoute>
  </s:Header>
  <s:Body>
    加密数据
  </s:Body>
</s:Envelope>

在现实世界中,针对此类挑战的稳健解决方案将更加复杂,并且会更好地分解;也就是说,将识别常用的标头元素,以便可以单独定义它们并适当地嵌入到其他标头元素中。但是,这些示例说明 SOAP 标头扩展有效地将元数据和操作指令附加到消息,而不会干扰消息正文,并且大大简化了单个服务的开发,因为许多操作需求可以由其他服务或公共消息管道(稍后章节中探讨的概念)来满足。此外,SOAP 消息的自包含性质提供了通过一个或多个中介路由它并持久化它以供稍后处理的机会,而不会丢失可能在传输协议中携带的上下文。SOAP 可以描述为传输不可知论的;一个设计良好的消息无论通过 HTTP、原始 TCP 套接字还是 SMTP 传递,都将同样有效。

SOAP 将通过扩展而不是规范继续扩大其用途。SOAP 规范很可能保持简单和灵活;任何添加都可能侧重于使其更具可扩展性而不是更完整。用户社区将开发、发布、采用和标准化新的 SOAP 标头元素以扩展平台。一个相当近期的例子是 WS-Security 规范的发布,该规范是通过 Microsoft、IBM 和 VeriSign 的合作开发的。WS-Security 定义了用于加密和签名消息以及将证书(例如身份验证令牌)附加到 SOAP 消息的 SOAP 标头元素。您可以期待未来几个月出现更多此类发展。

非 RESTful 性

由于 Web 服务架构发展如此迅速,它是否已为现实世界做好准备?事实上的标准是正确的标准吗,还是 XML/SOAP/WSDL 标准包含致命缺陷?这位作者断言“document/literal”是正确的方向是否正确,或者他这样说是仅仅因为他在微软工作?本节将探讨 Web 服务架构可能缺乏什么,结论将留给读者。

“表述性状态转移”(REST)是由 Roy Fielding 创造的,用于描述对 Web 架构的反向工程视图。REST 追随者有时被误解为与 Web 服务对抗,但他们试图利用 Web 的成功原则来构建 Web 服务架构——使其功能足够灵活,以涵盖广泛的应用程序需求,同时又可扩展且可管理。REST 阵营中最关心的是,新兴的 Web 服务鼓励对所有交互使用单个 HTTP 谓词 Post。Fielding 的分析表明,正确使用几个众所周知的谓词——HTTP 支持 Get、Post、Put 和 Delete——是服务可管理性的关键。

代理服务器可以轻松地根据四个基本的 HTTP 谓词过滤和路由消息,如果它们被正确使用的话。Get 应该没有副作用,以保证幂等性并促进缓存。Post 应该被识别为不可缓存的,并且需要特殊支持以确保幂等性。Put 和 Delete 是绝对的并且自然是幂等的(但会引发多个写入器之间的并发问题),并且需要不值得缓存的响应。(请注意,这种幂等性观点忽略了对元数据的影响,例如“上次修改时间”。)使用 Post 查询 Web 服务会破坏缓存和 URI 可寻址性:Web 文档如何在页面上被引用或在所有形式的媒体中通过引用传递。因此,使用 Get 进行查询,使用 Post 进行修改;两者永远不会相遇。自 Web 的早期以来,这一原则就一直被违反。更新请求通常被编码到 Get URL 中,以实现用户体验目的(“单击此处确认购买”),以及使用 Web 表单中的 Post 进行复杂查询。但是过去的错误并不能使该原则失效。

如前所述,SOAP 请求的自包含性质是一个优势;它可以被存储、转发、发送回以进行澄清、重新提交,并且可以通过任何传输方式携带而不会丢失完整性。因此,SOAP 阵营的响应很可能是一组标头元素,这些元素阐明了其缓存签名,以及消息是否可以缓存、安全地重新提交等等。但是这些标头元素尚不存在,并且它们是否会被标准化到足以被每个网络缓存和代理服务器支持还是未知的。在此期间会发生什么?简单(过于简单?)的答案是 HTTP Get 不会消失。它对于 Web 服务协议本身的功能至关重要:WSDL 和 XSD 文档通常使用 URL 和 HTTP Get 引用和检索。

但这引发了一个问题:当 XML 消息可以使用成熟的 Web 协议和基础设施通过 HTTP 传递时,为什么要使用 SOAP 呢?我们已经讨论了支持自包含消息的论点,并暗示了支持传输不可知消息格式的论点;但是,如果该传输不可知格式只是 HTTP,并在必要时由其他传输方式包裹呢?这将要求将整个 HTTP 标头视为消息的一部分并相应地保留。SOAP 倡导者会说 HTTP 标头很笨拙(尤其是考虑到空格的重要性),并且在设计上不适合复杂的指令。有人认为,修改 HTTP 以支持 SOAP 所做的事情,等同于重新创建 SOAP。随着更多 SOAP 标头元素的定义和使用,这种论点的力量可能会增强。

“打哈欠,”您说。“当然,软件架构师正在互相争论。这不是他们的工作吗?我想知道的是:这些东西有效吗?” 嗯,是的,也不是。Web 服务技术存在一些限制,最大的限制是依赖于互联网可用性的解决方案的脆弱性。广域网是不可靠的,并且具有不可预测的延迟。无论您多么仔细地设计以避免阻塞网络请求,如果关键服务不可用,应用程序都无法进行。这个问题需要从组织上和服务设计上加以解决。

Web 服务实现的最新技术限制了互操作性和可以合理开发的应用程序。最突出的问题是较旧的 SOAP 工具包对 document/literal 消息风格的支持不均衡。第一波 SOAP 使用的重点是 RPC 场景。许多工具包在实现 RPC 支持方面做得很好,但在支持文档风格方面做得不好。公平地说,XML 模式规范是在许多这些工具包编写之后才最终确定的。因此,您将需要仔细评估您的工具包功能如何影响您与合作伙伴组织互操作的能力。另一个实际问题是平台的不成熟性,尤其是在前面讨论的扩展功能方面。仅仅为了与供应商交换发票而解决安全性、路由协议、可靠消息传递和事务支持等问题是没有意义的。

许多人担心 XML 的冗长性,包括所有命名空间声明和元素名称,会淹没网络或拖慢调制解调器连接速度。幸运的是,XML 压缩效果良好,现代调制解调器会压缩文本以进行传输。但是,并非所有网络堆栈都这样做,因此预计未来会看到该领域的工作。相关的担忧是将数据编组为文本(即将二进制数据转换为文本以进行传输,然后再转换为二进制数据以进行处理)的性能影响。坦率地说,这是互操作性的代价。对于大多数现实世界的服务,转换仅占其 CPU 利用率的一小部分。但是对于某些需要高事务率的服务,二进制协议简直是必需的。

另一个担忧是我们最终会得到各种各样的标准和应用程序服务器,它们无法互操作。正如老笑话所说,关于标准的最好之处在于有太多标准可供选择。Web 服务技术(从 SOAP 标头元素到工具包再到高端应用程序服务器)的互操作性是一个至关重要的问题。技术供应商必须将互操作性作为首要任务,市场和行业媒体必须让他们兑现承诺。一个有希望的发展是 Web 服务互操作性组织 (WS-I) 的成立。WS-I 是一个行业联盟,致力于定义协议套件的配置文件,Web 服务技术必须根据这些配置文件证明其合规性。WS-I 的主要交付成果之一将是测试套件,用于建立各类技术与其相关标准的合规性。

Web 服务真的为黄金时段做好了准备吗?Web 服务当然可以在您的关键任务系统中发挥重要作用,但目前它们需要“非原生”基础设施的支持。您可以通过路由到 MQSeries 服务器来获得可靠的消息传递;您可以使用传输级加密获得安全通信;您可以在现有系统上进行身份验证和授权(与您目前忍受的劳动密集型协调相同)。随着时间的推移,“原生”解决方案将利用 Web 服务架构的优雅集成功能。

服务模式

它并不完美,但对于许多类问题,Web 服务架构是最合适的可用技术。Web 服务对于向客户端组件的异构网络公开状态管理服务特别有用。让我们看一下部署 Web 服务的场景。此处检查的服务模式倾向于包含比传统设计模式更大的功能块,传统设计模式通常限定在组件级别。

1. Web Services Façade(Web 服务外观模式)。外观模式是一种常见的组件设计模式,它为一些“不友好”的应用程序逻辑提供了一个“友好”的接口。外观模式最常见的用途可能是隐藏对外部资源的调用,例如数据库,因为数据库可能需要与应用程序其余部分不同的语言或语法。外观服务模式与之类似;它充当非原生 XML 服务组件的 XML 前端。Web 服务外观通常托管在其前端服务的附近,必须满足原始服务的信任要求。在实现外观时,请仔细考虑身份验证、授权和用户模拟的实现。如果回调到原始服务的调用使用特权帐户(例如 Unix 超级用户),它将破坏服务通常提供的任何授权检查,因此外观必须重新实现这些检查并经过仔细测试。当行业向原生 XML 接口转型时,外观的例子比比皆是;以下是一些例子:

2. 公开 Web 后端的数据。 Web 服务的承诺之一是创建“可编程的 Web”。由此可见,Web 服务将用于公开当前通过网页支持的数据和功能。本质区别在于,数据的编码方式将超越通过浏览器可用的信息“图片”而被利用。

公开 Web 数据允许合作伙伴和客户将服务功能嵌入到满足其需求的界面中。网站不必提供其数据的每一种理想视图;它可以让各种应用程序(从通用分析工具(如电子表格)到专用智能客户端应用程序)检索和操作数据。XML 为合作伙伴提供了一组稳定、自描述的接口,而不是迫使合作伙伴“抓取屏幕”HTML 来查找相关数据。

公开数据以进行临时利用,极大地提高了信息的杠杆作用。想象一下,如果将您的位置发布为 Web 服务意味着永远不必再指路,世界将会发生怎样的变化。这种模式特别适合具有事务性商业模式的网站。只要最终客户购买商品或服务,Web 服务提供商就乐于提供其数据的多种客户端表示形式。依赖广告收入的网站公开 Web 数据的意愿会降低。

3. 拦截。 拦截模式通过路由、重定向或重传在客户端和最终 Web 服务提供商之间提供中介服务。通过路由,客户端根据先前的指令将消息发送到拦截服务。该指令可以通过本地配置(例如 LAN 上的默认路由器)获得,服务的 WSDL 文档将拦截服务定义为端点;或者通过运行时引用,客户端被告知如何将后续请求路由到服务。重定向通常是传输协议(如 HTTP)的一个功能。重传将由接收服务执行,消息在最终处理之前发送到一个或多个其他服务。

此模式可以以多种方式使用。我们在今天的 Web 上看到的拦截服务是代理服务器,它“拦截”Web 流量以提供安全性和缓存服务。随着 Web 服务的增长,我们可以期望看到更复杂的加速服务,将可编程功能推送到整个网络的服务器场。最终,这可能会导致“虚拟服务器场”,体现“按需计算”的概念。拦截模式也可能被身份验证服务使用,该服务收集客户端身份证据并插入 SOAP 标头以证明调用者身份。Web 服务版本控制可能包括动态路由旧格式的请求,通过能够将请求转换为新格式的不同网络端点。此外,复杂的转换(例如自然语言翻译)可以通过拦截服务执行。

4. 业务流程管理。 Web 服务可以协调大型组织和联盟之间的复杂流程,范围从员工招聘(需要招聘组、人力资源、IT、会计和薪资部门之间的协调)到汽车保险索赔处理(跨越保险公司、理赔员、维修店以及通常是医疗服务提供商和警察的组织信任边界)。Web 服务在流程管理方面具有独特的优势,因为它们是围绕被管理的状态而不是系统或技术特性而设计的。这种技术不可知论弥合了无数的业务流程系统。

跨不同信任域的流程管理中的一个挑战是处理对服务状态的事务性更新。事务管理中的传统技术侧重于在更新之前锁定受影响的行,并且仅在所有各方都同意事务可以继续进行时才提交更改。这种方法在低信任度、高延迟连接和不可靠传输的环境中效果不佳。在长期运行的事务(也称为“saga”)领域正在进行有趣的工作,其中包括临时提交和补偿操作,以便在必要时取消事务。纯回滚在这样的事务中通常是不可能的,因为时间和对服务状态的其他更新的影响。

5. 产品目录发布。 产品和服务目录可能是企业可以为客户、合作伙伴和销售渠道提供的最灵活的数据馈送。销售团队成员可以通过笔记本电脑在客户访问期间随时掌握它。支持人员可以更新它作为与客户的通用参考,以及常见问题解答的关键沟通渠道。组织网站可以消费该馈送并将 XML 数据呈现为 HTML,供当前和潜在客户使用。XML 产品目录的优点在于它收集相关的产品数据,同时允许客户端选择相关的详细数据。销售自动化工具将显示现有库存,而消费者工具可能会比较与竞争产品的特性。在将目录作为 Web 服务发布时,您必须根据消费者与组织的关系来限制消费者可用的数据。将目录作为 Web 服务发布的最大挑战在于定义模式。最佳策略是利用垂直市场细分中已经存在的内容,并尽可能兼容地扩展它。

由于多种原因,目录可以从服务代理中获益:您提供的客户端代码,以方便访问您的 Web 服务。首先,数据往往相对稳定,因此客户端的智能缓存有利于服务可伸缩性和用户体验交互性。其次,数据通常很复杂,帮助客户端实现更常见的操作场景将提高服务利用率。

6. 信息门户。 自 Web 诞生以来,“门户”和“仪表板”就提供了有价值的服务,范围从消费者新闻网站(如 My Yahoo! 和 The Motley Fool)到 IT 部门开发的网络管理站点。Web 服务为构建这些门户提供了一种新方法,通过定义用于交换其有价值的数据的通用方法和模式。通过 Web 服务公开数据,数据发布者使客户端能够消费数据,而无需承担向客户端解决方案开发人员带外传输模式和接口指令的支持成本。这种情况与前面关于公开 Web 数据的章节相关。内联网和外联网门户不会受到该章节中描述的商业模式问题的影响,但它们确实引入了围绕授权访问到分隔的组织信息的更复杂的问题。

7. EAI 中心。 企业应用程序集成 (EAI) 是传统上昂贵的在业务应用程序之间构建数据交换系统的过程。EAI 解决方案必须了解它们管理的应用程序的协议和服务接口,从不同的应用程序中提取数据,并将数据转换为其他应用程序理解的模式和类型。EAI 解决方案的有效模型是中心。中心通常将提取的数据转换为内部表示,从中它可以生成所有它服务的应用程序理解的表示。中心可以使用连接器方法来模块化地向安装中添加受支持的应用程序。

在 Web 服务世界中,数据的内部表示是一组 XML 文档,连接器是 Web 服务外观,它们从受支持的应用程序的内部数据生成这些文档。然而,认为问题到此为止就结束了,这未免过于天真。虽然 Web 服务是 EAI 解决方案的有效架构,但开发工作仍然非常复杂。在应用程序供应商承诺业务数据的通用模式,并构建能够支持这些模式的 XML 接口之前,业务数据转换将仍然困难且容易出错。以这种方式“商品化”他们的产品不符合应用程序供应商的直接利益,因此需要客户需求才能在该领域取得很大进展。

Web 服务设计

为了熟悉技术套件,最好从小处着手,采用“爬行、步行和跑步”的方法来发展 Web 服务专业知识,并建立组织对 Web 服务架构的信任。“爬行”可能包括在您的组织内部构建 Web 服务。选择一个当前解决方案笨拙的项目——也许是一个信息服务,需要用户运行终端仿真器并使用神秘的命令。在应用程序前面构建一个 Web 服务外观,并通过网页或智能客户端应用程序公开该功能。“步行”可能包括使用 Web 服务公开订单状态服务的只读数据。准备好向您的合作伙伴和客户宣传该解决方案,并协助他们使用它。您可能在一段时间内还无法“跑步”,这取决于关键基础设施服务(例如跨域身份验证机制)的开发和标准化速度。当您外部化您的 Web 服务时,组织和技术基础设施问题也需要解决。这将需要与您的客户和服务提供商达成明确的服务级别协议 (SLA)。

开发完整、健壮、可伸缩的服务可能需要您以不同的方式思考。例如,Web 服务将使 XML 模式(现在是您的数据库架构师的晦涩领域)成为组织如何沟通的核心。当 Web 服务既支持您的内部流程又支持您的外部数据视图时,它们的效果最佳。驱动您业务的信息的一致视图——一致的数据模型——保证您和您的客户保持同步。首先研究您的行业中正在进行的模式工作。参与该过程以确保代表您组织的利益,并遵循良好的设计原则。好的 XML 模式是:

为安全性和可靠性而设计。当您逐步运行 Web 服务时,您将需要开发用于身份验证和授权的系统复杂性。您早期的内部服务可能只是简单地使用您现有的域访问系统,例如 NIS 或 Active Directory。但是在开发对外部用户进行身份验证的服务时,请避免为他们创建和管理身份。使用合作伙伴管理的凭据对来自合作伙伴组织的用户的身份进行验证。查看 WS-Security 规范和相关活动,以了解如何将这些凭据附加到 SOAP 消息,以及接收服务如何验证其有效性。消费者服务应利用用户 ISP 或互联网规模的身份验证服务提供的身份。后一个领域非常活跃,包括 Liberty Alliance 和 Microsoft Passport,但要使“通用单点登录”成为现实,还需要做很多工作。

您的 Web 服务需要支持多种类型的访问。每个人都可以访问的信息可以分配匿名访问权限。需要特定信息的客户、合作伙伴和供应商可以获得经过身份验证的外部访问权限。员工拥有访问和修改信息的最大权限,可以获得经过身份验证的内部访问权限。您可能还需要更精细的控制;例如,您的人力资源主管可能需要广泛访问人事记录的权限,而其他员工只能访问他们自己的信息。实现这种精细授权的最佳方法是通过基于角色的安全性。对于每个 Web 服务,确定数据将如何被访问和修改,以及这些活动映射到哪些角色。例如,管理工作日历的 Web 服务可能会向日历所有者授予完全访问权限;允许指定人员添加和删除与工作相关的承诺;允许同事查看但不修改与工作相关的活动;并允许经过身份验证的外部合作伙伴查看用户何时可以参加会议。因此,对于这个假设的 Web 服务,您可能会定义四个角色:所有者、助理、同事和合作伙伴。需要基础设施服务来支持将个人身份映射到这些角色。

组织网络内运行良好的 Web 服务应该很少出现可靠性问题。网络延迟应该很低,计划内的停机时间很容易公布,并且变更管理足够简单,可以在午餐时间解决。但是,跨组织边界访问的服务(尤其是在有些不可预测的公共互联网上)带来了更大的挑战。服务级别协议可以设定期望,并在事情出错后提供追索权。专用连接可以减少关键服务的延迟和网络停机时间。良好的编程实践可以消除您在超出 LAN 范围获取数据和应用程序服务时不可避免地遇到的小问题。一个好的策略是不阻塞服务访问。确保您始终有一个控制线程来清理无响应的请求并采取补偿措施。“线程池”(其中保留了多个工作线程以“唤醒”和管理高延迟工作项)是访问 Web 服务的良好设计模式。

此外,预计访问会失败,并准备好管理它。智能地管理失败请求的重试,注意考虑重复请求对增量更新服务状态的影响。有时资源在可接受的时间限制内将无法访问,因此设计流程以优雅地失败,同时通知需要调查的适当人员。还要记住,缓存相对静态的数据可以减少网络不可靠的影响;它还可以减少等待外部服务所花费的时间。如果可能,请在您的服务生成的文档上提供显式缓存指令,以便客户端组件可以减少其服务请求。最后,合理地使用 Web 服务。服务的价值必须证明访问它的延迟是合理的。即使在局域网上,您也不会调用 Web 服务来执行整数加法。

Web 服务版本控制。与任何组件编程模型一样,客户端应用程序将绑定到特定版本的 Web 服务。Microsoft Windows 因 DLL 地狱而臭名昭著,其中通过新安装的应用程序更新共享库会破坏绑定到早期库版本的旧应用程序。注意不要创建 XML 地狱。XML 模式和 WSDL 文档必须使用版本控制方案进行更新,以避免破坏现有客户端。客户端实现通常会为其访问的 Web 服务创建服务代理和数据反序列化器。服务代理外观将服务调用隐藏在具有应用程序正在编写的语言的本机绑定的函数中。此代理派生自服务的 WSDL 文档中定义的服务接口,如果这些接口发生更改,则会失败。序列化和反序列化将 XML 数据元素转换为本地类型,以便于处理。但是,如果数据元素模式发生更改,这些将会中断。虽然可以忽略对服务接口的一些更改(尤其是当新元素的 SOAP “mustUnderstand”属性为 false 时),但指望客户端优雅地处理更改是不良做法。对 XML 模式、WSDL 协定以及遵守这些协定的服务所做的更改必须以向后兼容的方式进行版本控制,以支持现有客户端组件。最好的方法是在唯一的命名空间中创建新的模式和协定。

在 XML 模式中,命名空间是使用“schema”元素的“targetNamespace”属性指定的。在 WSDL 文档中,使用“definitions”元素的“targetNamespace”属性。命名空间可以是任何 URI,以便您可以灵活地命名和版本控制您的服务。一种方法可能是将传统的版本号编码到 URI 中:targetNamespace=“http://orgname/serviceName/versionNumber”。当您发布新版本的服务时,请在通过递增版本号创建的新命名空间中进行发布。通过使用新的命名空间,您可以防止为旧协定编写的客户端尝试调用新服务。但是旧客户端也将被限制更新自己以利用新功能。如果您不继续支持旧接口,则现有客户端将中断。为了避免必须维护服务逻辑的多个实现,请考虑使用前面描述的“Web 服务外观”模式来转换旧格式的请求和响应。

设计指南。Web 服务的独特优势和局限性表明,设计模式与传统组件软件系统中使用的设计模式不同。这些包括:

基于上下文和内容的路由。Web 服务实现可以分布在许多物理设备上,托管在全球多个数据中心中。服务逻辑可以根据任何消息元素或属性将请求路由到特定的服务实例。一个示例是根据调用者身份路由到特定的服务集群,这对于互联网规模的电子邮件服务提供商可能是必要的。

准备好了还是没准备好,它们都要来了

随着互联网成为数据和应用程序集成的骨干,用于描述我们的世界和我们交互的通用模式将解除组织之间信息流的阻塞,并使我们能够以前所未有的精确度进行通信。但是,这种转变要求从小型企业到世界各国政府的组织重新考虑如何管理数据和流程。与此同时,软件行业必须交付技术,使人们能够表达和操作驱动我们的业务、我们的社会和我们的社交互动的信息。Web 服务有望成为转型各个方面的核心。


关键概念

• 组织现在可以在运行时检索最新数据,但现在必须就检索和更新数据的协议达成一致。这种必要性催生了 XML Web 服务,它试图弥合无数的互联网系统。

• 良好的 Web 服务不是建模为远程过程调用 (RPC),RPC 主要支持在紧密耦合但在拓扑上分布的系统之间进行方法调用。尽管 Web 服务和 CORBA 之间存在很强的类比关系,但 Web 服务提供了更大的灵活性。

• 在未来几年,我们将在两个领域经历创新浪潮:XML 模式的定义,作为跨互联网的组件间通信的通用语言,以及 SOAP 标头元素的定义,以扩展 Web 服务消息传递能力。

• Web 服务技术存在一些局限性,最大的局限性是依赖互联网可用性的解决方案的脆弱性。无论您多么小心地设计以避免阻塞网络请求,如果关键服务不可用,应用程序都无法进行。

• Web 服务当然可以在您的关键任务系统中发挥重要作用,但就目前而言,它们需要“非原生”基础设施的支持。您可以通过 MQSeries 服务器路由获得可靠的消息传递;您可以通过传输级加密获得安全通信;您可以在现有系统上进行身份验证和授权。

• Web 服务架构通常是最合适的可用技术。它为外观和拦截模式、业务流程管理、产品目录发布、信息门户和 EAI 中心提供了新的方法。随着时间的推移,“原生”解决方案将利用 Web 服务架构的优雅集成能力。

• Web 服务的独特优势和局限性提出了独特的设计模式,包括大粒度消息、异步消息传递、服务的双向性、端点发现、幂等性、服务代理以及基于上下文和内容的路由。

• 用于描述交互的通用模式将解除组织之间信息流的阻塞,并使我们能够以前所未有的精确度进行通信。但是,要实现这一目标,需要在数据和流程管理方面进行新的思考。Web 服务有望为组件间通信带来 Web 为人与人之间的通信实现的开放连接,这将成为转型各个方面的核心。


MIKE BURNER 是微软的软件架构师,致力于 Web 服务。Mike 最近的工作包括协作技术、基于 Web 的存储服务以及参与 .NET My Services 的规范制定。在加入微软之前,Mike 在 Alexa Internet 工作,开发 Web 分析技术、基于 Web 服务的联合技术和互联网档案。Mike 对集成和互操作性的迷恋源于他早期的职业生涯,当时他曾在哈佛大学和施乐公司担任 Unix 系统程序员和系统管理员,他的日子都花在了让 Unix 版本、VMS、CMS、Mac、PC 和施乐网络服务彼此友好地配合工作上。

acmqueue

最初发表于 Queue vol. 1, no. 1
数字图书馆 中评论这篇文章





更多相关文章

Niklas Blum, Serge Lachapelle, Harald Alvestrand - WebRTC - 开放 Web 平台的实时通信
在这个疫情时期,世界比以往任何时候都更依赖于基于互联网的 RTC(实时通信)。过去十年,RTC 产品数量呈爆炸式增长,这在很大程度上是由于更便宜的高速网络接入和更强大的设备,但也归功于一个名为 WebRTC 的开放、免版税平台。WebRTC 正在从实现有用的体验发展到在疫情期间对于数十亿人继续工作和学习以及保持重要的人际交往至关重要。WebRTC 的未来机遇和影响确实引人入胜。


Benjamin Treynor Sloss, Shylaja Nukala, Vivek Rau - 重要的指标
衡量您的站点可靠性指标,设定正确的目标,并努力准确地衡量指标。然后,您会发现您的服务运行得更好,中断更少,用户采用率也更高。


Silvia Esparrachiari, Tanya Reilly, Ashleigh Rentz - 跟踪和控制微服务依赖关系
如果您曾经将钥匙锁在房屋或汽车内,那么您会对依赖循环感到熟悉。没有钥匙就无法打开锁,但没有打开锁就无法拿到钥匙。有些循环是显而易见的,但更复杂的依赖循环可能很难在它们导致中断之前找到。跟踪和控制依赖关系的策略对于维护可靠的系统是必要的。


Diptanu Gon Choudhury, Timothy Perrett - 为互联网规模的服务设计集群调度器
希望构建调度系统的工程师应考虑他们使用的底层基础设施的所有故障模式,并考虑调度系统的运营商如何配置补救策略,同时帮助租户系统在租户系统的所有者进行故障排除期间尽可能保持稳定。





© 保留所有权利。

© . All rights reserved.