示例:SOA模型示例•问题描述•项目范围和目标•服务标识•服务设计•服务实现问题描述在此示例中,我们来看看一个选择将其销售点(PoS)终端的应用程序所使用的特定功能作为服务重新实施的零售商所面临的问题。现在,贸易应用程序是作为单个应用程序开发的,该应用程序有非常紧密耦合的组件,但有些组件驻留在商店内服务器(ISS)上,有些请求甚至被ISS转发到位于企业中心的服务器。问题是,由于组件的紧密耦合以及在组件的开发和不同组件之间的连接中使用了专有协议和技术,所以一般的商店基础结构和特定的贸易应用程序很难维护。在以前的商店系统中,PoS终端使用专有和低容量的机器,对于商店内和商店外的带宽有限制,现在这些限制大多已不存在了。知道了这一点,以及现有的在企业后端系统中向面向服务的体系结构的转变,我们已决定ISS提供的一些功能和中央服务器应作为服务对贸易应用程序显现。项目范围和目标昀初要考虑选择的功能都有一个共同的模式:它们当前要求贸易应用程序中的逻辑在多个数据存储器中查询信息。这样,提出的服务不仅提供了一个公共的接口,还使贸易应用程序与数据位置的明确了解脱离,且不必处理多个协议。•客户查找;这是一个在终端执行的两步流程,对于已从商店中购买商品或在商店获得对商品的服务的客户,在商店里有一个本地数据库。如果在存储数据库中找不到客户(对数据库和执行的SQL查询进行直接连接),则贸易应用程序将使用消息队列方法通过ISS上的查询服务器查询中央客户数据库。新服务将位于ISS上,并作为与贸易应用程序通信的单个点,应用程序将与ISS通信,ISS将反过来查询本地数据库,然后将请求转发给中央服务器上的另一个服务(实施相同的服务规范),中央服务器将查询其本地数据库。•服务调度;在此情况下,客户希望对他们购买的商品调度服务,当前,贸易应用程序必须查询客户数据库(请参阅上文)和中央保证数据库,看该商品是否受保证,并用客户规划引入商品的日期/时间更新服务调度。看起来有更好的方法解决这个问题,新的调度服务将如下运行。给定商品的序列号就能查询保证数据库;此数据库已经包含客户标识,因此可同时抽取客户数据。如果客户只有商品的类型标识,则我们必须照以前那样为客户和商品进行查询。所有这些都将由服务完成,除去贸易应用程序的逻辑。•库存检查;在此情况下存在类似的问题,服务首先查询本地实时数据库的库存,如果找不到商品,则它将查询包含较少产品信息但包含所有存储库存(除了前一天晚上批量更新,所以不受保证的那些库存)的企业数据库。新的ISS服务将聚集以上的查询,但还将为中央服务器提供实时更新,以将库存更改事件传递到中心,并使得对其他商店的查询更准确。这意味着中心的库存服务能接收这些库存更改事件,而本地服务则不能。这些服务将通过RMI从贸易应用程序访问ISS服务,并使用SOAPoverJMS从ISS到集中服务。服务标识以下内容概述了体系结构团队所执行的步骤,该团队包括拥有IT组织的零售商成员和作为开发面向服务解决方案的专家引入的外部顾问。请注意以下步骤并不表示推荐使用的RUP活动,只是列出了实际项目的活动。重要的是,注意此项目将改进当前现有功能的技术实施,所以没有花太多的时间在业务建模或分析上,因为我们可以复用为原始贸易应用程序创建的模型。当前的模型集(在下图的左边)遵循以下所示的结构,其中显示了RUP用例模型、贸易应用程序公共组件的分析模型、详细的设计模型和一组用于Java开发团队的实施模型。服务模型被作为分析模型的改进引入(在上图的右边)到一组具有其自己的实施模型的服务中。现在可修改贸易应用程序设计以显示这些公共服务的用法,另外还显示了贸易应用程序和服务Java模型之间的关系。服务模型创建如下图所示,存储支持服务模型是根据软件服务的UML概要文件和模板模型(包含在RationalSoftwareArchitect中)创建的。如以上所示,该模型被标识为分析模型的改进。正如您所见,在显示模板推荐的视图之间依赖关系的概述图中体现了该结构。用视图包旁边的图链接可以快速浏览模型,这些链接将在以下部分完成。有关更多信息,请参阅工具向导在RSA中创建服务模型。标识服务分区(位置)从以上对问题的描述可知,对系统分区有多种方法,例如我们可以引入代表库存管理、服务/保证管理、销售点操作(查找价格、客户等)的分区。但是,这些不是体系结构的主要问题,所以添加到模型的分区代表在商店中或在企业级别提供的服务的逻辑位置。当我们说这些是逻辑分区时,我们就确定了商店服务分区包含一组在商店级别实例化的服务,我们并未描述这些服务的物理部署(单服务器、集群等)。为体系结构提供这些逻辑分区来代表解决方案的重要方面。另请注意,在上图中,体系结构引入了另一个元素,即贸易应用程序本身,以描述应用程序和服务之间的通信。贸易应用程序是UML2.0组件,其构造型为服务使用者。有关更多信息,请参阅解决方案分区概念。分析现有功能下一步是分析贸易应用程序的当前实施,查看以上问题说明中标识的数据库访问的详细信息。因此生成了下表(注意它仅包含客户和库存查找的详细信息)。名称技术输入输出注释sp_get_custlist_by_phoneSQL服务器存储过程phonenum(10个字符)列表:custid(id)custname(40个字符)此存储过程通过电话号码返回了客户详细资料列表,该列表可呈现给客户以供选择。sp_get_cust_details调用用于返回一个客户记录。sp_get_cust_detailsSQL服务器存储过程custid(id)客户记录返回了客户的详细资料:姓名、地址、联系信息等。CUST_QUERYIBMMQSeriesphonenum(10个字符)返回队列名称(120个字符)相关标识(120个字符)不适用应用程序将要查询的客户的详细资料放入此队列,消息被交付到中心,在那里服务器将应答消息公布到标识的返回队列。return-queue-nameIBMMQSeries不适用相关标识(120个字符)客户记录列表返回客户记录时,返回消息还包含相关标识,以确保可将应答与给定的请求关联。这允许商店内的服务器有一个所有终端的返回队列,终端用其相关标识来查询响应消息的队列。sp_get_invstate_for_skuSQL服务器存储过程sku(13个字符)库存记录INVENTORY_QUERYIBMMQSeriessku(13个字符)返回队列名称(120个字符)相关标识(120个字符)不适用return-queue-nameIBMMQSeries不适用库存记录正如您所见,这些条目代表现有的实施,该实施将被替换为新的实施,但将保持原来的用途和功能。初始服务规范开发活动服务标识引入了一些支持解决方案所需的标识服务的技术和对服务的操作。在此示例中,我们看到了一种以旧换新的形式,将现有功能转换为服务模型和特定的服务实施技术。要执行此操作,首先要开发服务规范集合,该集合将提供实施以上所述功能的服务合同。下图显示了在此阶段创建的三个当前为空的服务规范,每一个用于介绍中讨论的一种服务。接着,我们分析服务可能的使用模式,例如,我们实际上可以有两种服务,一种用于商店内,一种用于企业,其中,数据库访问和企业访问的逻辑都包括在商店内服务中。我们也可选择在商店中有一个外观服务,该服务包括该逻辑并调用两个相同的服务,一个包括本地数据库访问,另一个包括企业访问。第二种选择在更改对两个商店的逻辑访问方面增加了灵活性,但对于比较简单的功能而言则增加了开销和通信成本。所以,对于客户查找和库存查找,选择了第一个选项。虽然服务分发的详细信息和服务提供者尚未确定,但是如果仅侧重于服务规范,则服务标识将有效得多。要标识这些服务的角色和职责,我们使用服务协作和一个特定的UML2.0组合结构图,该图代表客户查找的服务的配置。该结构图如下所示,我们可以看到代表协作中每个元素的UML2.0部分。注意,贸易应用程序和商店内服务之间以及商店内服务和企业服务之间的接口的构造型为服务通道,并标识要使用的绑定(如以上所标识的RMI或JMS)。商店内服务和本地数据库组件(较迟)之间接口的绑定未定义。这里要注意的一个关键元素是LocalCustomerLookupProvider是一个生成的服务,它是围绕数据库查询的一层很薄的包装程序服务,有一个代表SQL选择的操作。该方法是由商店内客户查找服务通过直接访问数据库选择的,以允许本地服务包括其他业务规则,或甚至在以后成为更完整的服务。但是,此图仅显示了协作的结构,以下交互图(UML2.0时序图)代表了服务之间的实际通信。请注意我们已将操作getCustomerByPhone添加到服务规范。另请注意,UML2.0允许指定时序图的可选“片段”,在此情况下,表示如果本地查找失败,我们将只与企业服务通信。将静态结构与通信图结合使我们能够记录服务组合和协作,并在此情况下意识到对服务规范只需执行单个操作。有关更多信息,请参阅活动服务标识。服务设计获得来自“服务标识”活动的模型后,我们将对一组候选服务的确定转换为要构建的服务的详细设计。第一步是制订实现以上规范的服务规范;正如您所能想到的,在服务如何实现以上模型的服务规范方面要作出许多决定。在此示例中,我们有相当简单的结构,但该结构可能对于许多项目都是相同的。在此情况下,我们有一个服务提供者,提出实现一个规范的一个服务。当然,每个供应商都可以有多个服务。我们还注意到此模型中各服务之间的一些使用关系,这些依赖关系对于理解服务如何随时间演进是很重要的。此结构允许我们现在更多地转移到分发空间,而当服务提供者表示部署服务模型的单元时,模型仍然是服务的逻辑视图。定义组合服务也需要服务提供者,因为服务本身(UML2.0端口)不能拥有描述该组合所需的结构。消息设计在服务标识活动中,我们前面未谈到关于服务规范中描述的各操作之间交换的实际消息。这可能是很普通的方法,根据推迟消息的详细设计的操作来捕获服务的职责,在某些情况下,此方法被倒转,消息结构已提前知道,然后被聚集为一组操作。在此情况下,我们能利用作为组件分析模型的一部分开发的领域模型(以前开发的资产),所以我们的消息模型并非无任何内容,而是标识了要复用的领域模型的子集。以下的示例说明了这个关系,领域类完全不知道技术和平台,另一方面,我们的消息被认为是数据传输对象和在服务之间传递的结构。所以我们不改变领域模型,而是在类结构“之外”创建消息,包含内部的元素。有关更多信息,请参阅概念消息设计。服务实现在此情况下,我们将侧重于实现商店内的客户查找服务;此服务通常在从服务模型到设计模型的转变中。该转变本身在指南中有记录,它导致以下模型结构。虽然这仍是设计模型,我们可以使用工具将此模型进一步变换为以下所示的EJB实施。基本上,此实施是从以上的CustomerByPhone类转变而来,详细描述客户的消息被转变为用于查询数据库的实体bean。有关更多信息,请参阅指南从服务到服务组件。