任务:消息设计
本任务描述了开发综合消息设计模型(类别)所需的操作。并作为背景论述了消息交换模式以及领域模型与消息模型之间的关系。还概述了消息详细程度和消息性能的设计考虑。
规程:分析和设计
关系
主要描述
通信服务和组件之间的消息是 SOA 的关键部分。它们不仅包含给定服务调用的输入和输出消息,还包含信息流经过应用程序体系结构的各层时,在企业中使用的内部消息格式。在许多情况下,建议使用公用消息格式。

由于服务包含输入和输出消息,本任务的重点在于:

  • 确定并规范服务的输入和输出消息格式和内容,
  • 服务与底层数据模型的关系,
  • 内部公用消息格式和考虑事项,以及
  • 如何在这些消息之间建立映射。

服务模型的消息规范应从企业体系结构/应用程序体系结构、数据体系结构和集成体系结构方面考虑。 这包括:

  • 以企业或应用程序级别定义的消息标准
  • 作为数据体系结构一部分的合适的元或数据模型
  • 作为集成体系结构一部分的消息变换标准

在规范过程中,了解组织在体系结构的三个方面的标准(如果可用)十分重要。 消息规范和数据模型是紧密相连的。数据模型由底层实体和其关系构成,其中的一部分可作为输出消息的组成部分发出并作为来自入局消息的输入接收。因此,消息格式与底层数据模型或数据体系结构之间的映射是主要的体系结构考虑事项。 在某些情况下,模式和其实施(例如企业服务总线)可以处理消息的变换(和路由)。 在许多情况下,我们可能需要外部处理程序来实现消息和数据模型之间的变换。

在大多数面向对象程序设计语言中,行为调用基于方法调用或消息传递范例。例如,C++ 使用函数指针的表来调用正确的方法。而 Smalltalk 则传递在执行时间评估其接收方的消息。面向服务的解决方案本质上是基于消息的,虽然与编程语言的绑定可以为客户机提供基于方法的接口,但与服务或服务之间的通信却不是这样的。服务消息传递的另一面是现在越来越多的服务都用异步接口开发,这与方法调用的基本同步特征相反。

在企业集成领域,有一类技术已成功使用了多年:面向消息的中间件(或 MOM)。这组技术是产品(如队列管理器和消息代理)中的清单。它还为 IT 组织提供了灵活、可伸缩和强健的方法用于松散连接的应用程序。

已意识到面向服务的体系结构(SOA)是基于组件的开发的演进。在某些方面,此演进考虑了很多从 MOM 的成功中吸取的经验:如何有效地松散耦合系统。MOM 基础结构提供了以下特征,该特征允许通信系统独立地演进。

  • 消息队列,用于可靠的消息传递,即使在网络或系统失败的事件中。
  • 消息路由,都是指针对性能和可靠性的网络路由,高级路由基于消息内容。
  • 消息变换,这样当接收服务能接受“项目”的请求时,调用服务就能公布“产品”的请求。
  • 消息适配器,允许 MOM 知晓服务寻址最初并不是用 MOM 接口开发的系统。
步骤
使用消息标准
为已确定的服务定义消息规范时,考虑企业的消息标准(如果存在)很重要。如果没有定义消息标准,明智的作法是开发它们。 如果存在行业消息模式,建议您利用它们。 例如,已为金融业、政府、旅游业(OTA XML [Open Travel Alliance,http://www.opentravel.org/online_schema.cfm])定义了 XML 消息传递规范。  此外,OAGIS [开放式应用程序组,http://www.openapplications.org/index.htm] 还提供了不特定于行业的模式。

公用消息格式

公用消息是指在多层体系结构的各层间传送的消息。 通常情况下,用户界面信息被捕获并发送至控制器层,在业务或应用程序层中进行处理,然后再传递到持久层或后端旧系统。  在这些传送过程中,在各个层间交换的同一条消息都可能有不同的格式。 最关键的是在企业内就公用消息格式的标准达成一致,以便在所有不使用企业服务总线(ESB)或格式转换方面的代价很大的情况下克服所有格式转换开销。 ESB 的使用将省去许多协调、变换和路由。 这是 SOA 层模型中描述的集成层。

在某些情况下,它能够就出局消息和入局消息的格式达成一致。 公用消息格式的问题是关键的体系结构决策:您可以选择此处指定的“自己选择”、采用行业模型(如旅游行业的 OTA XML)或采用不特定于行业的模型(如 OAGIS 定义的模型)。 在某些情况下,此决策将使用公用企业消息格式来更新消息中的字段并将其传递到下一层进一步处理。 如果由于政治因素而无法实现此类公用模式,则可以设计将消息转换成内部公用消息格式的适配器。 它们也可以用作 ESB 的一部分。

ISV 考虑事项 :如果消息调用在 ISV 软件包内实现的服务,则可能需要对此类消息加以扩充,这样才能满足 ISV 软件包数据模型内的约束。 此类数据元素可通过分析在 ISV 软件包组件内实现的服务来确定,或通过 ISV 软件包由下至上的服务分析来确定。  由于在服务实现之前这些属性可能无法确定,因此一旦确定,可能需要将它们更新到公用消息。

公用消息格式和数据体系结构

一般而言,服务不应表示任何关于底层数据模型的信息。 而应该用于封装底层数据模型,这些模型的数据存储由实现服务的服务组件使用。 因此,作为查看、编辑、删除、添加搜索以及对数据库的其他操作的服务可能不是很好的候选服务,但可以如现今那样将它们用作底层组件操作。

定义概念、逻辑或物理数据模型的现有数据体系结构是定义公用消息格式所必需的源。 公用消息格式的定义应与数据体系结构工作和数据模型相协调。  此分析将确保实现新服务的服务组件的合适数据存储和模式的可用性。  如果需要向底层系统添加新的数据,则应增强现有的数据体系结构以适应新的服务。

在很多企业中,现有系统通常反映了通过批处理协作的纵向结构与数据岛的存在。 通过服务方法从隔离的数据存储迁移是可能的。 对服务供应商数据源的确定是在服务实现过程中完成的。

ISV 考虑事项:逻辑数据模型需要适应通常包含在 ISV 软件包中的预定义数据模型(通常为隐式)。 因此,在打包的应用程序与现有数据模型之间需要进行消息转移。  这通常是通过 ISV 提供的 API 完成的。 在 SOA 中,这些 ISV 数据模型的适配器变得很重要,尤其是在 ISV 没有通过服务显现其底层数据和功能的情况下。

请注意,在 ISV 数据模型可访问时,可以对模型进行定制以适应支持已确定服务所需的消息。 相反,如果数据模型不可访问,服务消息传递可能受到包含在 ISV 内的数据模型的约束。 也可以采用一种协调机制来解决此问题。 可在此环境中使用协调(例如 ESB 所提供的适配器)来支持与 ISV 软件包的连接。 ISV 数据模型还指示了除实施服务所必需的属性以外的其他属性。

与所有相关服务关联的公用消息格式

公用消息格式必须与各个服务的输入/输出消息的格式一致,因此它们被关联并分配以允许相应的服务在需要时使用并更新它们。 服务可能需要从公用企业消息格式中抽取信息或接收输出。 在“服务公用消息格式”模板中对它们进行了记录。
复用领域模型

在概念概念:领域设计中,简述了领域建模的概念,它与分析模型或业务分析模型的概念类似,都代表业务领域中的核心概念(与技术无关)。 很明显,(如果在用于 Web Service 的 XML 模式的情况下并非特定于技术的话)服务使用的消息是知晓技术的,同样,用于存储领域数据的数据库模式在服务内也是特定于技术的。事实上,我们可以考虑以下关系。

文本内容中所述的图。

这显示了将一组元素传递到服务并从服务返回时,用于发现主要领域元素的领域模型和作为领域模型实现的消息模型之间的关系。

文本内容中所述的图。

以下是典型的 Java/组件模型,其中我们可以看到将“接口”与“类”分开以及包含“访问者”函数,以获得和设置状态变量的值。这是一个很常用的方法,但它也有缺点,如果使用者和组件位于不同的地址空间或者不同的机器,因为要访问任何一个组件的整个状态,所以每次调用的通信成本都很高。

文本内容中所述的图。

另一个问题是组件之间的关系,一个帐户有一组客户的概念很难以此样式开发,通常最终以管理用于检索个别对象的标识列表的形式结束。

开发服务模型时,我们可以使用数据驱动的服务确定方法,生成 AccountMgr 服务和 MeetingMgr 服务的规范。第一个服务规范作为管理所有帐户和联系人的中心位置。事实上,客户关系管理(CRM)解决方案的核心数据模型是使用该服务规范及其他服务构建的。第二个服务已被单独使用,因为 CRM 解决方案和其他解决方案可以用它来预定会议,并且它将与企业群件应用程序对接。

以下是该模型的样本;它显示了服务规范,这些消息可从以上的领域模型中获得。

文本内容中所述的图。

了解消息交换模式

考虑消息时,自然倾向于将它们当作操作的参数。 这种情况更有可能发生,因为服务的 UML 说明使用带参数的操作,Web 服务描述语言(WSDL 1.1)使用类似的方法。但是,在考虑服务服务规范方面时,将消息方面视为服务操作所生成或使用的可复用元素将更有帮助。在服务用语中,操作成为消息交换,虽然指定的服务交换与另一个可能使用相同输入和输出消息的交换不同。

消息交换模式的概念成了 Web service 标准世界中的兴趣所在,作为在开发标准以支持其规范中对服务使用的分析的一部分。消息交换模式指定了两个服务之间(或服务和使用者之间)生成的或使用的消息的特定组合,并为服务设计人员提供了公共的词汇表以描述对服务规范的操作。

以下内容列出了可在服务规范的定义中使用的公共交换模式。此类模式通常可在服务协作的建模过程中找到。

同步请求/响应:这实际上是传统的方法调用,其中服务使用者发送消息至服务,然后一直等待直到收到来自该服务的答复。

文本内容中所述的图。

单向消息:在此情况下,使用者只发送消息至服务,而不等待或期望答复。此模式可以被视为无答复类型的异步方法调用,意思是在发送消息后服务使用者继续执行,而不是等待服务处理消息。

文本内容中所述的图。

通知:在此情况下,服务负责将消息回送给使用者(通常是另一个服务)。要实现此操作,使用者必须通过某种方式向服务注册,这样服务才能知道将通知消息发送到何处。

文本内容中所述的图。

异步请求/响应:这是单向消息和通知的结合。服务使用者发送消息,包括回复地址。当服务完成其处理时,它将回叫发起方。如果服务使用者以异步方式发送第一条消息,则要求他们跟踪所有已发送的请求,以便可以将从服务接收的响应与原始请求相关联。

文本内容中所述的图。

发布/预订:这也是一种结合。服务使用者用发布服务表示对“主题”感兴趣。其他服务或服务使用者发布消息(发送消息)给发布服务,标识与该消息关联的主题。如果主题与先前注册的使用者匹配,则将通知他们有新消息。在这种情况下,可以很松散地耦合参与的服务。任何使用者或发布者都只需知道发布服务的位置,并且可以毫不费力地将新使用者添加到解决方案。

文本内容中所述的图。

管理消息详细程度

服务旨在提供很详细的操作。这样,流进和流出这种操作的消息也倾向于很详细。原来在部署 Web Service 解决方案的早期曾强调过这个问题,在解决方案开发期间使用 HTTP 作为传输、SOAP 作为协议、XML 作为有线格式会导致响应较慢且需要较高的带宽。例如,请考虑来自服务的库存报价请求。简单的库存报价通常在 Web Service 的早期就会显现。订单符号是四个字符,响应是十进制数字。在 RPC 样式的二进制协议中,我们可能期望消息标识能添加一些开销,比如 8 个字节,这样我们就能期望在请求的 8+4 区域中和响应的 8+8(对于高精度十进制)区域中的某处。对于 HTTP/SOAP,我们可以期望获得以下格式的内容:

请求 响应
  SOAPAction: "http://www.webservicex.net/Quote"
User-Agent: MyAgent 1.0
Content-Type: text/xml; charset=UTF-8
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tns="http://www.webservicex.net/">
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<tns:Quote>
<tns:Symbol>IBM</tns:Symbol>
</tns:Quote>
</soap:Body>
</soap:Envelope>
  HTTP/1.1 200 OK
X-Powered-By: ASP.NET
Connection: close
Content-Length: 522
X-AspNet-Version: 1.1.4322
Date: Mon, 21 Mar 2005 00:34:21 GMT
Content-Type : text/xml; charset=utf-8
Server : Microsoft-IIS/6.0Cache-Control: private, max-age=0
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<QuoteResponse xmlns="http://www.webservicex.net/">
<Quote><Last>89.28</Last>
</Quote>
</QuoteResponse>
</soap:Body>
</soap:Envelope>

Web Service 技术的早期接受者得出两个结论。首先,由于少量操作将数据作为文档提供,而不是作为传统组件模型的更复杂的样式提供,服务得到优化。这样做的优点是可以跨更大的实际数据有效内容分期偿还协议的开销。另外,在企业中的各服务之间,至少在同一解决方案内的各服务之间,会选择较小和较简单的协议绑定,并会在必要时(如与企业外部的服务连接时)保留 HTTP/SOAP。

此概念并非全新的概念。即使在组件领域,价值对象模式或 J2EE 服务外观都是减少客户机和服务器之间通信往返次数的方法。两者都使用了发送组件状态的完整副本到客户机的概念而不是使用传统的存取器功能。对于服务,我们可能还要考虑正在开发的服务与业务模型(特别是业务流程模型)更加接近的事实。这样,消息就能反映一般的业务文档,就象 EDI 事务集(电子数据交换)代表诸如订单、发票、装运通知单等业务文档一样。

管理消息交换性能

通常,使用大型消息在提高通信性能方面是很有价值的,尽管在某些情况下,大型数据消息可能是个问题。例如,在以上的 SOAP 消息中,我们看到使用 HTTP、SOAP 和 XML 后,消息大小如何显著地增加了数据的大小。这导致了用户对使用 Web Service 技术构建的早期系统的不满。另一方面,这些问题使我们获得了一些有趣的经验,如根据代码性能、消息设计和协议选择将性能当作早期设计活动。

要考虑的一个重要方面是,当我们将大块状态从服务移动到使用者或者从服务移动到服务时,这些消息实际上代表服务状态的旧文件快照。所以,其中一个考虑是通过标识数据被视为可靠的时间来明确管理这种“旧文件”,或者将其“租借”给使用者,这样它在一段时间后就会过期。关于更多信息,请参阅白皮书 Using Service-Oriented Architecture and Component-Based Development to Build Web Service Applications

另一个要考虑的主题是高速缓存内容。高速缓存通常是作为应用程序的性能优化来处理的问题,但在面向服务的解决方案中,分布式特征和基于消息的通信有助于在使用者和服务之间使用高速缓存。这些高速缓存不是用于优化查询的典型数据库高速缓存,更象是在 Web 服务器和 Web 代理中使用的高速缓存。事实上,在使用 HTTP 和 SOAP 的 Web Service 中,这些代理可被用作在特定情况下提供服务响应的高速缓存。

但这些关于高速缓存使用的问题实际上是高速缓存如何理解用于服务高速缓存内容的策略,以及服务如何能使高速缓存无效。用于主管和管理部署服务的技术基础结构应该提供高速缓存功能。我们将来期望看到的一个服务策略领域就是提供高速缓存管理信息。

更多信息