你的位置:首页 > ASP.net教程

[ASP.net教程]第6章 服务模式


抽象使我们能够为在运行时进行交互的分散的软件块指派行为和数据。在体系结构完善的系统中,这些交互共同构成一个内聚在一起的可执行智能,从而为企业提供切实的业务价值。

上一章介绍了使用基于实例的协作和由近链接分隔的系统来将单个应用程序分布到多个处理节点上的模式。您可能已经回忆起来,“近链接”是连接驻留在同一个信任区域和同一个企业内的分布式系统的可靠链接;近链接不需要互操作性。远链接是所有其他链接(包括跨越 Internet 的链接)。本章主要关注通过远链接连在一起并且使用基于服务的协作的系统。

在构建由近链接连在一起并使用基于实例的协作的分布式系统时, 开发组织通常能够完全控制解决方案中涉及的所有组件。但是,很多大型企业应用程序包含由远链接分隔的系统,不得不与预先已存在的、通常不受开发组织控制的系统交互。例如,订单管理系统可以使用在预先已存在的系统中实现的信用评分功能或者由外部服务提供者提供的销售税额计算服务。因此,复杂的解决方案有可能 必须与由外部组织控制的功能进行交互,而且必须按其原样使用。

本章重点介绍应用程序和外部服务之间的协作。为了描述 Web Service 如何提供便于这种协作的互操作环境,本章概述了下列主题:

  • 基本协作概念
  • Web services
  • 使用 Web Service 实现的基于服务的协作模式

协作概念

类、 对象、组件和接口是现代软件的基本构建单元。其中的一些元素用于封装问题域,而另一些元素则提供系统基础结构和技术体系结构。每个构建单元都提供一个有用 的功能,但是实际功能取决于为一个企业(或许多互相联系的企业)提供实际业务价值的协作解决方案中各个元素的综合效果。为了实现这种级别的协作,软件元素 必须遵循约定的组织原则,并且必须互相公开标准接口。如果组件不相似,则一个元素必须适应另一个元素,或者二者必须都要符合约定的标准。

基于服务的协议

第 5 章介绍了基于实例和基于服务的协作的概念,并重点介绍了每种方法的优缺点。基于服务的协作非常适合以下情形:使用服务的应用程序无法控制远程服务,或者必须与在不同的编程语言或平台之上所开发的解决方案实现互操作。

基于服务的接口负责公开用来向潜在使用者提供服务的接口的单个实例。在 Web Service 上下文中,Microsoft 将软件服务定义为“用于将适合通过网络进行访问的基于消息的接口公开的、离散的应用程序逻辑单元”。[Microsoft02-2]

服务不依赖于调用它的进程;它是独立的并与上下文无关。这将允许网络中的任何潜在使用者访问服务。可以用指定服务请求及相关回复的格式的合约方式很好地定义服务。

虽 然不一定要基于消息,但是在分布式应用程序出现之前,在应用程序开发中使用了创建一组逻辑分组服务的概念。例如,操作系统向其上运行的所有应用程序提供服 务,如 Microsoft Windows? GDI 库提供图形服务,开放式数据库互连 (ODBC) API 提供数据库访问服务。正如将操作系统的一些核心功能抽象为一组服务有助于简化应用程序编程模型一样,标识企业的核心业务功能并将它们封装为一组互操作服务 有助于简化与企业防火墙外部的模式进行协作。

面向服务的体系结构

面向服务的体系结构 (SOA) 将服务概念应用于分布式企业应用程序。在 SOA 中,每个应用程序都将高级业务功能以服务的形式公开,以便供其他应用程序使用。因为这些面向服务的解决方案的范围很广且比较复杂,所以面向服务的体系结构 除提供调用远程服务功能以外,还必须提供其他功能。其中最重要的功能包括:

  • 使服务可在运行时找到。 独立应用程序能够很容易地找到操作系统服务(如 GDI 调用),这是在名为 gdi32.dll 的本地动态链接库中实现的。但是,企业服务可能会跨许多计算机、网络或设备分布。其中的一些服务是绑定到现有应用程序的,所以其位置可能会发生变化。因 此,在面向服务的分布式体系结构中查找服务可能是一项复杂的任务。
  • 让服务和使用者约定公用格式。 找到正确的服务之后,使用服务的应用程序必须能够动态确定要使用哪个协议来访问服务、如何格式化请求以及期望哪种类型的响应。因为服务可以使用各种语言和平台实现,所以使服务和使用者约定公用格式也可能是一项颇具挑战性的任务。

服务合约

当 一个方法调用应用程序内的另一个方法时,该方法签名定义了此方法与调用方之间的“理解”,例如,传递到该方法并在完成时返回的参数的数量和类型。因为调用 方和方法进行了许多隐式假设,方法调用可将它们的理解嵌入到一个简单的方法签名中;例如,这两种方法都在同一个进程中执行,并且使用共同的内存空间;这两 个方法都使用同一种编程语言;在被调用的方法完成之后,执行权将返回给调用方法。在分布式 SOA 世界中,其中的许多假设不再有效,并且需要在服务合约中明确写出。

服务合约必须指定如何实现用来连接服务使用者与服务提供者应用程序(如网络协议)的通信信道。服务合约还必须指定服务可以使用或生成的消息种类 — 用交互中所包含的每个消息的详细架构来描述。

图 1 显示了面向服务的体系结构的元素。

 

图 1 SOA 中的服务调用

单个服务可能需要支持多个合约。例如,同一个组织中的服务使用者可能需要通过一系列粒度相对较小的消息与该服务交互,并被允许访问敏感功能。为了提高性能,组织外部的服务使用者可能希望以粒度更大的方式与该服务交互,并且将不被允许访问敏感功能。

在调用远程服务时需要执行下列步骤:

  • 1.发现:服务使用者(任何希望访问某个服务的应用程序)查询提供所需服务的位置的服务储存库。
  • 2.协商:服务使用者和服务提供者协商一个由服务合约指定的通信格式。
  • 3.调用:服务使用者调用相应的服务。

Web Services

Web Service 提供基于标准的 SOA 实现。Web Service 定义一套技术和协议,它们可以大大简化基于一组协作应用程序创建解决方案的过程。在与 Web Service 相关联的多种技术和原理中,下面两个功能非常重要:

  • 服务提供者和服务使用者之间的通信合约
  • 互操作性

通信合约

协议栈通常用来比喻系统之间的通信,最众所周知的化身是开放式系统互连 (OSI) 分层模型。协议栈将通信描述成通信双方上的一组分层服务,而且较高层使用较低层的服务。例如,应用程序协议(如 FTP 或 HTTP)可以使用 TCP/IP 传输协议,TCP/IP 传输协议又使用以太网卡通过连接来移动位和字节。

通信合约详细定义了该协议栈中的所有层。例如, 电话系统提供硬件层,用来实现特定频率范围 (400 – 4000 Hz) 内的语音通信以及 MTDF 拨号。但是,如果两个通话者虽然使用兼容的电话硬件却说不同的语言,则他们仍不能正常沟通。如果您曾接到来自拨错的国际呼叫者或来自传真机的电话,就会明 白即使通信层正常工作,通信也可能失败。

Web Service 合约的工作原理与此类似。它需要解决通信的两个主要方面:

  • 公用通信信道
  • 数据表示和消息架构

公用通信信道

应用程序要想互相通信,它们必须使用兼容的协议。TCP/IP 已成为默认的核心通信协议栈。大多数(如果不是全部)操作系统都提供内置的 TCP/IP 功能。任何使用正确配置的 TCP/IP 栈的应用程序都能够与同一局域网中使用 TCP/IP 栈的其他应用程序通信。

图 2 显示了两个使用兼容协议栈的应用程序之间的通信信道

 

图 2 通信信道和 TCP/IP 协议栈

例 如,应用程序 A 可以向由应用程序 B 公开的 Web Service 发出请求。应用程序 A 的协议栈将应用程序级别的请求拆成一个或多个低级别的数据栈,以便通过网络传送。应用程序 B 的协议栈将数据包重新转换为应用程序级别的、对服务的调用。服务答复将经历相同的过程。

TCP/IP 协议栈的普遍存在性使其成为了互操作通信的理想基础。但是,TCP/IP 是低级别的协议,没有定义应用程序之间任何消息的内容。与电话线一样,它提供通信信道,但是未指定用来通话的公用语言。

HTTP 是一个位于 TCP/IP 之上的协议,它制定了请求外部资源时必须遵守的最基本的约定。HTTP 的简单性使其得到广泛支持,被用来通过 Internet 和跨企业防火墙传输信息。因此,HTTP 有利有弊。它的通用性使其最适于路由消息,但是它能够穿透大多数企业防火墙这一能力又令许多 IT 安全管理员感到不安。

增加 HTTP 后,其结果协议栈现在如图 3 所示。

 

图 3 增加 HTTP 后的通信协议栈

数据表示和消息架构

通信合约的第二部分处理通过通信信道所传递的内容,这相当于通过电话线所说的语言。合约的这一部分需要定义三项内容:

  • 数据表示格式
  • 消息架构
  • 消息到服务的绑定

数据表示格式

应用程序彼此之间要想成功地通信,则对于通过连接传递的数据,它们必须都遵循一组公用的数据定义。Web Services 协议栈已经限制了往复传递的数据必须采用文本格式。但是,文本数据代表什么?它是否代表序列化对象?它代表整数数组?还是

基本上可通过两种方法来提供有关数据所代表含义的信息:提供外部描述或使用自描述性数据。

外部描述以数据自身之外的某种形式定义数据的架构。分布式 RPC、DCOM 或 CORBA 技术使用的接口定义语言 (IDL) 是专用来编写外部描述的语言示例。编写数据描述的这种外部方法限制了互操作性,这是由于协作中涉及到的所有计算机都必须能够访问外部描述。

自描述性数据随数据自身嵌入数据描述。使用此方法可增加互操作性,因为不必查询数据的外部描述即可分析数据。

Web Services 使用

  • 它基于文本,因此与通信信道兼容
  • 它是业界标准,受到业界和用户的广泛支持
  • 它是自描述性的
  • 它具有互操作性

消息架构

消息是 Web Service 中的基本通信单元,因此所有协作方都必须正确理解消息内容。

通信合约必须指定与服务相关联的所有请求消息以及所有相关的响应消息。然后必须指定每条消息的内容。此任务通常包括标识每条消息的数据元素,指定元素的数据类型,指定与类型相关联或者类型之间的任何约束。

SOAP 将消息分成两部分:可选头和强制性正文。头包含与通信和服务基础结构相关联的信息。正文包含面向业务的消息内容,而头包含元数据。

消息绑定

定义好消息之后,必须将消息与通信信道相关联。除了 HTTP,SOAP 可以与其他基于文本的通信协议(如 SMTP)协作。因此,一个服务可以支持多个通信协议。

Web Services 使用 Web Services 描述语言 (WSDL) 提供服务所支持的所有消息的详细规格。反过来,WSDL 使用

WSDL 将消息组合成操作。操作是与服务进行交互的逻辑单位,它被定义为请求消息以及与之相关的任何响应消息。

最后,WSDL 将操作与一个或多个协议(如 HTTP 和 SMTP)绑定,然后将这些绑定操作一起组合到一个服务中。除了指定与服务相关联的操作,WSDL 服务规格还记录服务的特定于通信信道的地址。例如,服务规格将记录 URL 以标识通过 SOAP 在 HTTP 上公开的服务。

互操作性

互操作性是以前讨论的通信信道和消息描述中的主要因素。Web Services 的其他几个功能对提高互操作性大有帮助。

开放式标准

使用传统方法实现分布式通信的一个主要缺点是:应用程序依赖专用的通信技术、协议和数据格式。

Web Services 完全基于一组广受支持且独立于平台的开放式标准。因此,几乎所有主流平台都能以一种或多种方式实现 Web Services 协议栈。这大大减少了实现和部署基于协作应用程序的解决方案所需付出的心血和成本。

服务储存库

Web Services 的最后一个难题是服务发现。服务使用者应用程序如何查找需要与其协作的服务?答案是提供一个包含服务描述的联合性服务储存库,并将这些描述与各种用来标识 特定服务的元数据元素相关联。例如,服务储存库应当根据几个不同的标准(如开发组织、宿主组织、行业类型和所支持的业务进程)返回指向服务的指针。

使用服务储存库大大减少了服务提供者和服务使用者之间的耦合,因为使用者只需引用服务,而无需在服务使用者内部对访问服务所需的所有细节进行硬编码。这就允 许服务提供者更改通信合约中的许多部分,而无需对服务使用者进行任何更改。提供者只需更新注册表。充分使用 UDDI 规格的应用程序在下次访问服务时将自动使用新设置。

UDDI

通用发现、描述和集成 (UDDI) 规范解决了 Web Services 的服务发现问题。互操作性是 UDDI 的主要目标之一,因此,UDDI 使用已在本章中讨论的许多技术和协议也就不足为奇了。

UDDI 的核心只是一个储存库,其中包含指向 WSDL 服务描述的链接。UDDI 为可能会与服务相关联的各种元数据定义了几个

模式概述

本章中的模式描述了如何在面向服务的环境中构造按自定义进行开发的解决方案。具体地说,这些服务允许您实现以下功能:

  • 以服务的形式公开应用程序功能
  • 封装由其他应用程序公开的服务的使用细节

图 4 显示了服务网关、服务接口和服务实现之间的关系。

 

图 4 服务元素

当您设计面向服务的系统时,如果将负责应用程序业务逻辑的元素与那些负责和服务通信并参与服务合约的元素分开,会大有帮助。分隔这些元素有助于实现分隔关注点这个一般设计目标,并改善可维护性、灵活性和可测试性。

Service Interface (服务接口)模式提供合约中构造服务提供者部分的指导。它讨论了如何使用服务接口组件:该组件封装与一组特定的服务使用者进行通信的细节,并调用一个服务实现组件来执行与服务相关联的实际业务逻辑。在 .NET 中实现Service Interface然后提供了一个具体示例,阐述如何使用 .NET Framework 来创建服务接口组件。

Service Gateway(服务网关)设计模式提供合约中实现服务使用者部分的指导。它讨论了如何使用服务代理组件:该组件封装与服务进行通信的所有低级别的细节,并公开针对服务使用者应用程序中其他组件的使用而优化的接口。在 .NET 中实现 Service Gateway 然后提供一个具体示例,阐述如何使用 .NET Framework 来创建服务网关组件。