在本篇文章中,我们继续定义 SOA 解决方案。我们对每一个服务的规范进行详细的建模。这些规范将会定义服务的消费者和生产者之间的契约。这些契约包括被提供的和被要求的接口,那些接口在服务规范中所扮演的角色,以及那些角色在提供服务中进行交互的规则和协议是什么。
本系列的第 1 篇文章:“SOA 建模 第 1 部分 服务识别”(请参见左上方的 本系列更多内容)描绘出了识别那些同业务需求相连接的服务的一种方法的大致轮廓。我们首先捕获实现业务任务所必须的业务目标。然后,对满足这些目标所必须的业务操作和过程进行建模。接着,我们将业务过程视作反映我们的最终解决方案所必须满足的业务服务需求契约的一种服务协作。然后,我们使用该需求契约来帮助我们识别它们被要求的服务及它们之间的潜在联系。这为链接到业务目标的业务相关服务的识别提供了一种形式化的方法。
在前一篇文章中,我们也查看了如何通过识别于业务相关的服务来最大化 SOA 解决方案的潜力。我们设计了基于业务需求的服务拓扑结构,并且将服务连接到反映服务解决方案所必须满足的
Service Requirements 契约的服务协作上。
在本文中,我们继续通过对每一项服务的规范进行详细的建模来定义 SOA 解决方案。这些规范将定义服务的消费者和提供者之间的契约。这些契约包括被提供的和被要求的接口,那些接口在服务规范中所扮演的角色,以及那些角色在提供服务中进行交互的规则和协议是什么。
我们还没有准备好开始对服务规范的细节进行建模。服务规范必须为服务的潜在消费者指定其需要知道的每一件事情,以便他们决定是否有兴趣使用该服务,以及如何使用它。它还必须指定服务提供者为成功执行该服务所必须知道的每一件事情。因此,服务规范就是消费者的需要同提供者的提供之间的媒介或者契约。
理想情况下,这一信息由单一地点提供。这使得为复用服务而搜索资产库和获得所有必要的信息变得十分容易,而且不需要在许多不同的文档中定位或者搜索相关的元素。服务规范至少包括这些信息:
- 服务的名称,暗示出其目的。
- 被提供和被要求的接口,从而定义由服务和需求消费者所提供的功能性的能力。请注意:这与服务是如何被执行的并不相关,而是与服务的消费者和提供者之间的相互作用相关。
- 指定功能性的能力如何被使用以及以什么样的顺序被使用的任何协议。
- 反映服务想要达到什么样的成功以及如何对其进行评估的约束。
- 服务消费者所期望得到的和服务提供者被期望提供的质量,例如花费、可用性、性能、脚印、任务的适宜性、和竞争信息等等。
- 使用服务的原则,例如用于维持安全性和完整性或者用于将服务从无能力恢复到成功执行的安全性和事务范围。
如同本系列中所有文章一样,我们将使用现已存在的 IBM® Rational® 和 IBM® WebSphere®
工具来建立解决方案并将它们链接在一起,从而我们能够根据需求验证解决方案并且更加有效的对变化进行管理。表1总结了我们将要开发例子的过程,以及我们将要使用的工具。除此之外,我们通过将
IBM® Software Services Profile 添加到 IBM® Rational®
Software Architect 中的 UML 模型中,为服务建模扩展了统一建模语言(UML)。
表1. 开发过程角色、任务和工具
角色 |
任务 |
工具 |
业务执行官 |
传达业务目标 |
IBM® Rational® RequisitePro® |
业务分析师 |
分析业务需求 |
IBM® WebSphere® Business Modeler |
软件架构师 |
设计解决方案的体系结构 |
IBM Rational Software Architect |
Web 服务开发人员 |
执行该解决方案 |
IBM® Rational® Application Developer 和 IBM® WebSphere®
Integration Developer |
我们首先回顾业务需求以及满足它们的被识别的服务,正如我们在 “SOA 建模 第 1 部分 服务识别” 中所详细描述的那样。图1将业务需求显示为业务中角色的一个协作、角色职责、以及角色如何相互作用的规则。
图1. 服务需求契约
这一服务协作反映了一个需求契约,该契约来自一个指定服务解决方案必须做什么的业务过程。它是与体系结构无关的但是正式的需求规范,它它并不过度约束
SOA 解决方案。所谓与体系结构无关,是指该需求契约只是指定了解决方案必须做什么,但是并没有指定如何去做。
图2显示了被识别的服务规范的总体情况,该规范将会制造解决方案并且使用依赖关系,同时指出它们打算如何被使用。
图2. 服务拓扑结构
最终,图3展示了您如何使用那些服务来实现您的业务要求。
图3. 满足服务需求契约
这就完成了对服务以及它们是如何同业务需求相关的识别。本文的剩余篇幅还将解释如何对服务规范的细节进行建模。这些服务规范在图2中被详细表示为接口。它们提供了许多在
Overview 中列出细节。
在完成这些接口后,您仍然不知道接口所描述的是哪一项服务参与者提供或者需要的服务,也不知道服务功能如何被执行(可能使用其他服务)。这些都将在讨论服务实现的下一篇文章中加以介绍。
一个服务规范需要提供如下信息:
- 服务的名称,指示出它是什么或者它做什么。
- 被提供和被要求的接口,描述服务的功能性的性能。每一个功能性都包括:
- 它的名称,通常是一个动词词组,指示出它做什么
- 任何被要求或者可选的服务数据输入和输出
- 任何消费者在使用该功能之前所期望具备的前提条件
- 任何 消费者 期望的并且是 生产者 必须提供的功能成功使用的后期条件
- 即使前提条件已经被满足,但是功能由于某种原因未能被提供时,任何被提出的期望或者错误条件
- 任何通讯协议或者规则,它们决定功能什么时候后能够被使用或着按照什么样的顺序被使用。
- 消费者期望被提供使用的或者同服务进行交互的任何功能。
- 在提供服务时,任何执行都必须满足的需求。
- 反映服务想要达到什么样的成功以及如何对其进行评估的约束。
- 服务消费者所期望得到的和服务提供者被期望提供的质量,例如花费、可用性、性能、脚印、任务的适宜性、和竞争信息等等。
- 使用服务的原则,例如用于维持安全性和完整性或者用于将服务从无能力恢复到成功执行的安全性和事务范围。
显然,本文不可能涵盖所有这些内容。特别是,我们将不会关注服务或者策略的质量。对于那些内容,将有专门的文章加以详细的说明。进一步地,它们可能明确一个服务特定的提供者,而不是特定服务的接口自身。我们要做的是,关注定义和使用一个服务的最根本的必须条件。
下面各小节详细描述了每一个在 图2 中被识别的服务规范。其介绍顺序是从一个非常简单的没有协议的服务规范,到一个反映一个简单的请求/响应协议的服务规范,再到一个更加复杂的、涉及到消费者和提供者之间多步协议和交互作用的服务。
时间进度服务
图4中显示的 Scheduling 服务规范十分简单。服务提供了两种功能性:一种是对一个生产时间表请求进行响应的能力,一种是创建一个运送时间表的能力。据我们所知,在这种情况下,没有一种使用这些功能性的协议。这两者都能够被消费者以任何顺序被使用。
图4. 时间进度服务规范
Scheduling 服务规范是在生产包中定义的一个简单的 UML 接口。它提供两种服务操作。每一种操作都具有前提和后期条件,并且它们能够提出例外。服务操作的参数被要求要么为服务数据(消息),要么为简单类型。这就确保了参数不会出现被引用调用或者被值调用的状况,服务数据被放置在哪里(在什么地址空间中),服务消费者或者提供者是否在操作数据的一个副本或者某些持久数据源,等等。所有这些需要确保服务不受其配置地点的限制。服务数据被定义在下面的服务数据模型小节中。
装运服务
Shipping 服务协议有一些复杂。想要运送产品的消费者请求运送服务。然而,运送者可能会花一些时间来决定产品被放置在哪里,它们是否在可用清单中或者是否需要被生产,以及运送产品的最有效的方式。因此,运送时间表使用前需要一段时间。消费者通常不希望等到时间表完成,因为这会阻止并行中的其他工作,或者不必要的将系统资源消耗在长进程上。
因此,IT 架构师决定在消费者和提供者之间使用一个简单的请求响应或者回叫协议。消费者请求运送,过一段时间之后,响应来自运送者的请求来处理完全的时间表。要对这一协议进行建模,我们需要指定生产者和消费者这两个角色,它们的职责、以及它们进行交互的协议或者规则。最后一部分是非常重要的,这是因为如果运送者接收不到一个运送请求,那么它们将不能发送时间表。
服务规范告诉您需要知道的关于服务的任何事情。这包括您必须满足的使用服务的需求(有时被称作 Use 或者 Usage
契约,请参见 Resources
中列出的 Daniels 和 Cheesman 的文章,再加上服务必须满足的应用的需求(有时被称作 Realization
契约)。这是您需要为业务需求捕获的同一类信息;除了主题区域和细节级别是不同的之外。您将在涉及服务消费者和提供者如何进行交互的 Service
Requirements 契约中定义该规范。
在这种情况下,我们使用一个抽象类来定义服务规范,如图5所示。
图5. Shipping 服务规范
ShippingService 规范涉及到两个角色:
- 角色 shipper 是一个提供者的角色。它负责满足其类型赋予它的运送的职责,即运送接口。
- 角色 orderer 负责处理运送进度表。这通过其 ScheduleProcessing 类型被显示。
将这些角色指明为提供者和消费者并不是必须的。在一个潜在的长期运行的会话中(可能涉及到多方),这些只是任意的区别。通过 Service
规范实现被提供的运送接口和使用被需要的 ScheduleProcessing 接口,也很容易看出谁是消费者、谁是提供者。
在运送者和订货人角色之间有一个连接器。它指出了在这些角色之间涉及某些交互作用的协议。requestShipping 交互作用为
ShippingService 类所拥有,它显示了这个交互作用是什么。
ShippingService 交互作用指定了订货方运送方角色之间交互的行为的或者动态的方面。订货方首先发送一个 requestShipping
消息(或者调用运送方的 requestShipping 操作),一段时间后,必须响应来自运送方的 processSchedule
消息。交互作用涉及到两条生命线:一条用于订货方,另一条用于运送方。这些对象实例就是 Service 规范类中的订货方和运送方属性。也就是说,消息在哪些角色之间通过连接器被交换。这是一个简单的、异步的请求/响应或者回叫模式,它是许多服务协议的典型应用。
ShippingService 协议通过使用任何 UML 2 行为被指定,这些行为可以是:活动、交互、状态机、或者不透明行为(代码)。选择哪一种来使用取决于建模者、他们更加偏爱的风格、或者问题域的适用性。
货品计价服务
为发货单计算初始的和最终的价格,涉及到订货者和货品计价之间一个更加复杂的协议。显然,initiatePriceCalculation
必须在 completePriceCalculation 之前被调用。然后,订货者必须被准备来作为结果的发货单。
我们能够通过使用一个指定发货方和订货方角色、它们的职责、以及它们之间如何交互的协议(会话或者规则)的抽象类来捕获这个协议。这就像
ShippingService 规范,除了交互作用仅仅是简单的请求/响应之外。为了服务的有效使用,服务功能性必须以一种顺序被调用。
图6中显示的 InvoicingService 服务规范捕获了这一协议。请注意该服务规范也执行了 Invoicing 用例。一个用力可能被用来反映服务指定的需求。该服务规范包括两个角色:发货方和订货方。这些角色的类型分别是
Invoicing 实现的接口和被使用的 InvoiceProcessing 接口。这些接口封装了角色(服务或者请求功能或者操作)的职责。服务规范中的
InvoicingService 活动为使用服务操作指定了协议,在订货方和发货方角色之间能够发生的实际交流。
图6. InvoicingService 服务规范
nvoicingService 是一个指定订货人和发货单之间的会话、交流协议、或者交互规则的类。协议的细节在该类的 ownedBehavior
中被捕获,并被用来为使用这一服务指定有效的交互模式。在这种情况下,该协议被表达为一种 UML 活动。
该协议指示出订货方必须在试图得到完全的价格计算之前,启动一个价格计算。订货方然后必须响应一个请求(在本例中是回叫)来处理最终的货物。一些请求货品计价服务的消费者只需执行这三种操作,但是这些指定操作的顺序是受到协议约束的。没有一个
InvoicingService 活动中的 ActivityPartitions 反映 InvoicingService 类中的角色或者属性。一个属于某个分区的操作祈祷行动指示出祈祷处于分区所反映的角色(行动的目标输入码正是活动分区所反映的角色)。
在这种情况下,在订货人和货品计价服务之间只有一种交互作用,所以服务规范类只有一个 ownedBehavor。在另一种情况下,消费者和提供者之间会有超过一种的交互作用,每一种都是用不同的协议。服务规范将拥有一个
ownedBehavior 为每一个会话指定有效的交互模式。
您并不知道哪个服务提供者执行了一个 InvoicingService。您也不知道哪个服务消费者可能使用它。您只知道任何一个消费者使用服务必须做什么,以及任何一个提供者执行它时必须做什么。
购买规范
最后,我们来看处理定购单的服务规范,如图7所示。
图7. Purchasing 服务规范
如同 Scheduling 服务规范一样,Purchasing 是一个简单的接口,它仅仅拥有一个为消费者处理定购单提供功能的操作,而这些消费者将返回一个完全的发货单。伴随而来的副作用是,订购的条目被生产(如果需要的话)并且运送给消费者。
该服务接口反映了在原始的 Process Purchase Order 业务过程中指定的功能性的能力。它反映了从那个业务过程中识别和设计的服务。
至此,服务规范被更加完整的定义。我们能够查看前面 图3 中所显示服务拓扑结构。回顾它显示了被识别服务的实例如何能够被使用来满足业务
Service Requirements 契约。但是那个图表没有很好的显示服务自身,它们是如何被连接的,以及在它们的交互作用中涉及到什么协议。既然服务规范已经被完成,您创建一个新的图表,来指示使用这些服务的服务参与方如何进行交互来实现该需求。您将在本系列的下一篇文章
“SOA 建模 第三部分 服务实现” 中再次看到这一图表,在那里它将被当作本例子中最终的完整的服务解决方案的出发点被使用。
图8显示了一个抽象的 Order Processing 组件,它为显示服务拓扑结构的另一个视图提供了上下文环境。它部分反映了将要提供或者需求服务(或者既提供又需求)的必须满足
Process Purchase Order 需求契约的顺序处理参与方。我们尚不精确的知道这些部分是什么(它们没有类型),但是我们能够通过指出它们在定义其如何交互的服务规范中扮演什么角色,结合它们想要满足的需求是什么,来指定它们需要做什么。
图8. 服务交互的细节
Order Processing 组件各部分之间的连接器,指出了各部分之间预期的交互作用。连接器的名称与它们契约的名称相对应,在这种情况下,这是相应的服务规范的协议。这指示出这些部分将必须提供和要求服务规范所指定的接口,并且根据服务规范的协议各部分将会使用的这些接口。在本系列的下一篇文章对服务实现的描述中,将对这件事是如何完成的进行建模。
我们还看到这些被放在一起的部分将会以一种满足 Process Purchase Order 需求契约的方式相互作用。因此,Order
Processing 总结出以下两点:
- 服务消费者和提供者(或者称之为参与者)需要满足业务需求,
- 表示这些参与者如何相互作用的连接和协议同样如此。
package org::crm 中定义的 Customer Relationship Management (CRM) 数据模型,定义了在这个例子中的
Purchase Order Process 模型中所有服务操作所使用的所有数据(请参见图9)。CRM 包反映了 Customer
Relationship Management 服务数据模型的设计,该模型能够在许多服务中被复用,甚至是由不同公司所提供的服务。服务数据是如何被发现和格式化的,以及它是如何同持久实体或者物理数据源相关联的,已经超出了本文的范围。我们这里所介绍的是该服务数据是什么,以及该模型如何被捕获。
图9. CRM 服务域模型
图9中所显示的服务数据中的每一个 <message>。服务数据就是在服务消费者和提供者之间进行交换的数据。用于服务操作的参数的数据类型既可以是消息也可以是简单类型。
请注意:
服务数据消息同 Web Services Description Language (WSDL) 消息并不一致。服务操作能够拥有任何数量的消息或者简单类型的输入和输出。服务操作能够被设计用作输入、输出、和错误消息,但是这并不是必须的,而且还将导致不合需要的邮戳数据耦合。
消息作为 数据传递对象(DTOs) 能够被轻易的在分布式环境中的地址空间之间进行交换。服务消费者和提供者并不关心数据存放的实际位置,因此他们假定自己拥有一些实际持久域数据的视图的一个拷贝。消息没有同一性。由于它们的等同性是基于它们内容的值的,而不是基于它们的身份的,所以它们是值对象。
消息反映了在可能的分布式环境中,服务消费者和提供者之间的数据交换。服务提供者通常也需要访问持久的数据,用于它们的执行设计。服务数据和服务执行设计中所使用的持久域数据之间的关系就是服务提供者及其服务功能性的执行的职责。通常,服务数据是域数据的一个选集和投影(或者视图)。虽然如此,服务数据如何从域数据中得到或者更新,取决于服务执行。服务数据对象(SDOs)
对于服务数据消息来说是一个非常有用的执行。它们还具备管理变化集和自动将变化提交到持久存储区的能力。服务参与者执行可能会用到这些功能,但是它们不需要在模型中被处理。
数据模型使用一个 <id> 规则来识别唯一可以识别类的实例的属性。这将成为贯穿服务模型的主题。这是因为 Web 服务和面向
Web 服务的 Business Process Execution Language (BPEL) 特别依赖实例相关性的业务数据或者基于值的对象同一性。
在本文中,我们对每一个被识别服务的服务规范进行详细的建模。这些规范将会指示被提供的和被要求的接口,那些接口在服务规范中所扮演的角色,以及那些角色在提供服务中进行交互的规则和协议是什么。服务规范定义了消费者请求和生产者服务之间的契约。
本系列的下一篇文章 “SOA 建模 第三部分 服务实现” 解释了服务是如何被真正实现的。服务实现首先决定哪些组件将会提供哪些服务。该决定对于服务可用性、分发、安全、事务范围、和耦合具有非常重要的含义。在这些决定做出之后,我们可以对每一项服务功能是如何执行的进行建模,从而对需求服务是如何被使用的进行建模。然后,我们将使用包含在
Rational Software Architect 中的 UML-to-SOA 转换特性来创建 Web Services 解决方案,该方案能够在
Rational Application Developer 或者 WebSphere Integration Developer
中被直接使用,来执行、测试、和配置完全的解决方案。
学习
获得产品和技术
讨论
|