在运行时使用 UDDI
Karsten Januszewski
Microsoft Corporation
2001 年 12 月
摘要:本文概述了在运行时使用 UDDI,讨论了 UDDI(公共注册表和 UDDI 服务在 Microsoft Windows .NET Server 中提供)如何用作 Web 服务的基础结构以支持客户端应用程序。
目录
- 简介
- UDDI 运行时基础结构
- 示例方案
- 创建 Web 服务:C# .NET .asmx
- 使用 Web 服务:C# Windows 窗体 .NET 客户端
- 其他方案
- 总结
简介
UDDI(通用说明、发现和集成)通常称为 Web 服务的“黄页”。虽然黄页这一类比对于帮助理解很有用,但它不能完整体现 UDDI 是如何并入基于 Web 服务的软件体系结构中的。黄页类比只涉及 UDDI 的设计时用法,即通过基于关键字、类别或接口的搜索来查找和使用 Web 服务的功能。从设计时角度来看,黄页类比十分准确:就象黄页将企业及其电话号码分类并编成目录一样,UDDI 将提供者及其 Web 服务分类并编成目录。开发人员可以在 UDDI 中查找 WSDL 文件和入口点,然后将这些 Web 服务并入客户端应用程序。
不过,UDDI 不仅仅提供设计时支持。黄页类比并没有提及 UDDI 如何支持运行时。发现过程结束后,UDDI 将扮演一个很重要的角色。在运行时通过编程方式查询 UDDI 这一功能使 UDDI 可以用作构建可靠而稳固的 Web 服务应用程序的基础结构。
UDDI 运行时基础结构
将 Web 服务集成到客户端应用程序中后,需要考虑可能会遇到的问题,其中一个关键问题是无法预测或检测提供 Web 服务的提供者的故障,或者从故障中恢复。如果 Web 服务出现故障,客户端应用程序可以采取什么措施?应用程序如何适当且动态地从失败的 Web 服务调用中恢复?
同样,从 Web 服务提供者的角度看,Web 服务的所有者如何动态更新更改内容?我们需要考虑将 Web 服务移到新服务器的情况。如何将此更改通过有效方式通知到 Web 服务的客户端?所有者如何在运行时分发此信息,而不会导致 Web 服务的所有客户端中断?
在上述情况下,UDDI 在提供基础结构以支持运行时 Web 服务方面能够扮演十分重要的角色。UDDI 通过定义调用规则来解决这些“服务质量”问题,该调用规则包括缓存绑定信息(如 Web 服务的入口点)以及针对此特定实现方式的其他参数。发生故障时,客户端可以发出运行时 UDDI 查询,用最新信息刷新缓存的信息。
上述规定的模式如下:
- 在 UDDI 中查找 Web 服务。使用此 Web 服务(以 UDDI tModel 表示)的 WSDL 文件以及入口点和其他配置信息的实现细节,所有这些信息都包含在 UDDI bindingTemplate 中。
- 为特定的 Web 服务准备一个客户端应用程序。在客户端应用程序中,缓存 Web 服务的唯一 bindingKey,以便在首次使用该应用程序时,从 UDDI 检索所需的所有信息。
- 当应用程序调用远程 Web 服务时,使用从 UDDI Web 注册表获得的缓存数据。
- 如果调用失败,则使用 bindingKey 值和对 UDDI 注册表的 get_bindingTemplate API 调用以获取新的绑定信息。
- 对新旧信息进行比较:如果不同,则重试失败的调用。如果重试成功,则用新数据替换缓存的数据并存储新数据以便以后调用。不过,如果返回的绑定信息相同,则提供者不进行任何更新,且应用程序将发生错误。同样,如果有新的绑定信息,但调用仍然失败,应用程序也会发生错误。
从 Web 服务提供者的角度来说,提供者应当知道何时可以更新该 Web 服务的 UDDI 项。当 Web 服务的提供者需要将流量重定向到新位置或者需要备份系统时,提供者只需激活备份系统,然后在 UDDI 注册表中更改入口点。此方法称为失败时重试,为客户端提供了一种在运行时从故障中恢复的机制。
示例方案
我们可以看一个示例,以了解此模式的工作原理。此示例方案涉及的是一家虚构公司的方案,该公司需要向其内部部门提供实时销售数据。因此,此 Web 服务不能公开,而只在防火墙内部使用。
首先,我们需要一个 Web 服务。在这种情况下,我们将提供一个非常简单的 Web 服务,它只支持 GetSalesTotalByRange 一种方法,这种方法使客户端能够获取一定日期范围内实时销售数据的瞬态图。
接下来将创建使用此 Web 服务的客户端。我们将客户端配置为可以缓存入口点和 bindingKey 信息,并为客户端设置一种机制,以便在发生故障时从 UDDI 注册表刷新客户端缓存。
创建 Web 服务:C# .NET .asmx
Microsoft .NET 框架大大简化了 Web 服务的编写工作。在本例中,我们将创建一个简单的 Web 服务,它只包含 GetSalesTotalByRange 一种方法,该方法使用两个日期作为输入参数,并返回两个参数。下面是一个实现了此目的的 .asmx 页,SalesReport.asmx:
<%@ WebService Language="c#" Class="SalesReportUSA.SalesReport" %>using System;using System.Web.Services;namespace SalesReportUSA{ [WebService(Namespace="urn:myCompany-com:SalesReport-Interface")] public class SalesReport : System.Web.Services.WebService { [WebMethod] public double GetSalesTotalByRange ( System.DateTime startDate, System.DateTime endDate ) { return 5000.00; } }}
此页应添加到虚拟目录中。要使客户端示例工作,请创建一个名为 SalesReportUSA 的虚拟目录 (http://localhost/SalesReportUSA/SalesReport.asmx)。请注意,此 Web 服务始终返回 5000.00 作为返回值。(要是销售报表能够有这样的可预见性就好了!)真实的应用程序应当使用数据库调用来检索此信息。对于本示例,只需要一个硬编码的值。
部署此 Web 服务的下一步是在 UDDI 注册表中注册该服务。此 UDDI 注册表是一个内部 UDDI 服务器,公开此 Web 服务没有什么意义。Microsoft 通过 Microsoft® Windows® .NET Server 提供本地 UDDI 服务。有关此功能的详细信息,请参阅 Windows .NET Server(英文)Web 站点。如果没有安装 Microsoft .NET Server,您可以使用 Microsoft UDDI 软件开发包 (SDK)(英文)在本地计算机上安装 UDDI。
可以通过两种方式在 UDDI 中注册 Web 服务:可以使用 Web 用户界面注册,或者使用 UDDI SDK 通过编程方式注册 Web 服务。SDK 使用起来非常方便,您可以参阅使用 UDDI 的 Web 服务说明和发现专栏中发布的代码示例。无论使用哪一种方法,都需要先将 Web 服务的 WSDL 文件注册为 tModel。UDDI tModel 是 XML 实体,用于表示接口和抽象的元数据,因此,WSDL 文件表示为 tModel。然后,您需要将 Web 服务的入口点注册为 bindingTemplate。UDDI bindingTemplate 是 XML 结构,用于表示有关给定 Web 服务的实现细节。有关 UDDI 架构及其与 WSDL 的关系的详细信息,请参阅 http://www.uddi.org(英文)和 UDDI“最佳实践”文档 Using WSDL in a UDDI Registry 1.05(英文)。
以下是使用 UDDI 服务完成上述步骤后得到的 UDDI bi