UML软件工程组织

 

 

面向服务架构和面向服务的应用程序开发
2007-11-26 作者:Steve Buzzard 来源:dev2dev.bea.com.cn
 

面向服务的应用程序开发(Services-oriented development of application,SODA)是一种重要的开发模型,它使企业能够在转换到面向服务架构(service-oriented architecture,SOA)的过程中调整业务流程。本文介绍了一种SODA方法。

面向服务的应用程序开发(SODA)

Gartner把SOA和SODA看作是未来计算的基本元素。SODA是一种开发软件的新方式,旨在专门用于SOA范例中。SOA代表了松散耦合的、粗粒度的异构组件的集合,可以使用Web services把这些组件结合在一起。从而提高开发人员的生产力、代码重用程度和业务灵活性。SOA 蓝图(www.middlewareresearch.com/soa-blueprints/)是行业的最佳实践和相关参考实现的集合,对于那些想转而使用SOA的人来说,它是非常不错的资源。

SODA首先以创建和组装服务和服务合同为中心,而把设计和实现用于实现服务的对象和组件推迟到解决粗粒度服务合同之后。SODA开发人员更多地注重应用程序内部及其相互之间的流程流,而对于创建底层系统的代码就没那么关心了。参见www.serviceoriented.org/soda.html,其中有对SODA的简要描述。

主要问题

下面描述的问题虽并非巨细无遗,却也说明了通常会影响开发过程的一些问题(特别是对于拥有多个开发团队的大型企业),通过转向基于SODA的开发方法可以缓解这些问题。

依赖性/瓶颈

与依赖性次序相关的瓶颈通常是最重要的问题。开发人员通常必须等待某处依赖性内容的设计和/或实现完成之后,才能够继续执行任务。其中一个问题就是多团队环境中的工作划分问题。在这种环境中采用的一种标准工作划分是,让不同的团队实现不同层中的相同垂直功能片断。这导致了这些与依赖性相关的问题的出现。

管理和缓解与依赖性相关的问题,对于确保开发人员继续在整个开发过程中保持高效至关重要;然而,如果依赖性问题的多个部分是并行开发的(当项目有固定的最后期限时通常如此),那么要“管理”它是不可能的。

针对企业的每次发布(迭代),数据模型的创建总是与相应的软件开发差不多同时开始,不会早很多,这种模式虽说不理想,但通常也无法避免。类似的,发布的域模型也不会在使用它的开发迭代之前完成。在构造数据和域模型的过程中,正确的规划对于避免这些问题是至关重要的,但是如果项目已经启动,就无法更改了(“下一次我们会采用正确的做法”)。这些问题会导致业务服务、对象/关系持久性映射出现瓶颈,而且会使企业应用集成(enterprise application integration,EAI)/企业到企业(business-to-business,B2B)开发人员要求,在他们能够开始大部分工作之前,必须完成数据和域模型。

工作划分

开发团队通常按照层进行水平划分(尤其是对于那些地理位置分散的团队)。可能一个团队工作在表示层,而另一个则工作在业务层。这种划分通常不是必要的,因为异地的团队可能无法访问业务层需要与之交互的后端系统。表示层功能的开发不需要访问这些系统(至少在设计和迭代的初始实现阶段中不需要)。但是这种工作划分本身就存在问题,即独立的功能(用例)部分的开发是由独立(通常是地理位置独立)的团队来完成的。这些团队通常通过到业务服务的接口和通过它们公开的数据传输对象(data transfer object,DTO)(http://java.sun.com/blueprints/corej2eepatterns/ Patterns/TransferObject.html)进行通信——这是一条标准的Java 2 Enterprise Edition (J2EE)最佳实践。在开发迭代期间,随着表示和业务服务的开发人员对他们的设计和随后的实现的深入理解,DTO的结构和内容通常都会改变。另外,DTO的结构/内容(通常)是由域模型的结构驱动的,而且随着它的发展,这种做法更加流行。如果同一个团队致力于一个端到端功能片断的开发(这个团队应该能够控制域模型、DTO、业务服务接口和相关表示的结构/内容),这些问题就可能会稍微缓解。这种方法的主要瓶颈在于一致地模拟与后端系统的接口的能力,以便异地的团队也可以获得完整的垂直片断。当布置好团队时,这类后端系统通常具有使用限制,尤其是当后端系统连接到另一个项目、部门或业务,并且/或者被它们所拥有时。

图1 使用WebLogic Workshop进行开发的连续性

SODA方法的作用

对SODA而言,所有的资源都被认为是服务(从前端的UI组件到与后端外部业务合作伙伴的交互)。在这里,绝大部分开发人员的首要开发行为是编排这些服务。当所选的SODA工具没有提供相应的功能时,则由少数几个J2EE和集成方面的专家负责开发服务的实现和/或扩展。

依赖性抽象——抽象(以及自描述和发现)是SODA的关键:对服务实现的抽象,对具体数据输入的抽象,以及对诸如在用户接口背后进行连接和业务服务开发之类的行为的抽象。

重新调整工作划分的重点——SODA方法提供了足够的自动化、实现抽象和模拟支持,从而允许更加逻辑化的垂直工作划分。每个团队都负责相关功能的一个完整垂直片断,而且并不是始终依赖于另一个团队(他们采用另一种方法),当前的水平划分就是这么做的。

支持业务流程设计——SODA允许设计人员以图形的方式同时开发表示和业务服务,专注于从Web页面到后端集成交互的流程流。可以以图形化的方式开箱即用地配置服务和数据转换。SODA工具在幕后自动实现企业架构和J2EE设计模式。

服务发布和发现——SODA工具通常提供一个统一描述、发现和集成(Universal Description, Discovery, and Integration,UDDI)服务器(或另一个类似的注册库),或者与之交互,因此支持把服务及其相关元数据轻松发布到一个集中的注册库。相反地,这些工具可以用于发现以前发布到注册库的服务。这允许设计人员只要通过点击鼠标数下,就可以发现和重用一个服务。如果服务不可用,而设计人员需要配置一个服务,那么就可以发布该服务,以便其他人可以重用。J2EE和集成专家可能需要重新构建一个服务或者扩展现有的服务,而且要使用SODA工具才能做到,这些工具使他们可以一致地访问UDDI注册库。使用所选的IDE和导入到SODA工具中的生成JAR文件,就可以构造EJB和POJO。使用Apache的Ant(http://ant.apache.org/)可以把这个过程整合在一起。

利用各种技术和不同层次的专业知识——SODA允许所有开发人员快速精通编排用例流程流和公式化发生在流进行时的数据内容和转换,只要求他们对业务域和用例有一点了解。表示专家将执行表示流的编排。集成/EAI专家可以并行地配置一些服务和数据转换,这些服务和数据转换是连接系统和业务之间的流程流所必需的。如果没有提供某种独立功能的开箱即用服务,J2EE专家可以定制该功能部分的实现。他们可以使用SODA工具把这些实现公开为服务,然后发布它们,以便其他人发现。

集成SODA

流程

使开发团队过渡到SODA方法不仅需要改变流程,还需要改变文化。下文描述了所需的关键改变,但是各处改变的基本重点必须是:

1.重新考虑设计和实现域、业务、用例和表示组件的方式。在传统的流程中,业务服务和用例服务之间通常没有差别,而表示服务实际上根本不被认为是服务。为了实现域的独立性(域可插入性),同时也实现业务的独立性,用例与业务服务之间必须存在差别。另外,组成Web页面表示和页面导航的组件被认为是SODA领域中的首个类服务:页面导航的编排与业务流程流的编排实际上在技术上没有区别。域、业务、用例和标识服务层的编排都是循环复合之一:

  • 表示服务是这样实现的:在页面流中编排动作服务,将它们与用例服务相交互,最后把控制权转交给用于呈现页面的一个或多个视图服务。
  • 用例服务是通过编排其他用例服务以及底层的业务和域服务而实现的。
  • 业务服务是通过编排其他业务服务和底层的域服务(跨多个域)而实现的。
  • 域服务是通过编排(同一个域中的)其他域服务而实现的。

2.使用支持SODA的工具的重点在于,为所有域和应用程序交互提供和增强它们实际需要的抽象。

J2EE/集成组件设计——对于那些在J2EE和集成技术方面的技巧和经验多过在业务和业务建模方面的知识的开发人员来说,应该安排他们去构建和/或扩展作为构建其他服务的基础的底层组件。

域服务设计——我们需要重点强调域服务设计(即以用例无关的方式与域模型交互的服务)。域服务必须是粘性的、不连续的和作用域有限的,这一点很重要。与特定域关联的服务集合应该允许该域可以独立于其他域使用。

业务服务设计——如果要求服务是独立于用例的,而且需要与跨域的底层服务交互,那么就应该实现单独的服务层。该层应该不同于且独立于单个的域服务,不应该把它合并到用例服务层中。本文中的业务服务是指跨单个域、同时跨用例实现保持独立性和可重用性的服务。同时,用例服务是特定于应用程序的,不能跨系统进行重用。用例服务和业务服务之间的关系类似于应用程序服务模式(www.corej2eepatterns.com/Patterns2ndEd/ApplicationService.htm)与会话外观(session facade,www.corej2eepatterns.com/Patterns2ndEd/SessionFacade.htm)之间的关系。

用例服务设计——通过编排其他用例服务和底层的业务和域服务,这些服务实现了特定的应用程序用例场景。这里需要深入理解特定应用程序的需求。

表示服务设计——这些服务编排页面流并在Web页面上呈现生成的信息。这里需要人为因素和HTML方面的娴熟技巧,并要从页面导航的角度了解应用程序流。

开发人员角色——如前所述,成功地集成SODA需要基于估计的技术集合明确定义开发人员的角色,而且任务分配也确实会影响到他们在流程中的角色。

工作划分——在SODA环境中,应该基于相关的/相互依赖的用例分组,从逻辑上对开发团队进行工作划分。

服务发布和发现——需要传授如何使用UDDI浏览器发现和使用服务,以及发布服务和进行版本控制(对于大部分组件来说,自动化这个流程是更可取的做法)。

配置管理——比较好的SODA工具与兼容SCC的源控制系统集成得很好,所以从这个角度看,配置管理不会从根本上有所改变。改变出现在处理已发布和确定版本的服务的过程中。基于SOA的系统通常会动态查找和使用服务。因此,服务的UDDI注册库应该与环境(如:开发、集成、QA、生产)进行分离,这和运行时系统本身几乎一样。还应该使用源控制系统对开发注册库进行同步。

与现有软件的集成——现有的基于组件的软件与基于SODA的新软件在源控制系统中是同等重要的。EJB和utility JAR,以及现有的Web应用程序,都可以被直接导入到大多数SODA工具中。大多数SODA工具还提供与GUI中所提供的功能等效的命令行功能。这是一种标准的需求,所以可以使用像Ant这样的工具来构建整个系统(不论是使用SODA技术开发,还是更加“传统的”基于组件/对象的开发)。

工具/集成服务环境(Integrated Service Environment,ISE)

在SODA中,有一个称为ISE的概念。ISE是指实际实现SODA概念所需的工具套件,是当前IDE逻辑演变的结果。SODA依赖于健壮工具集来处理接口抽象、发布、发现、模拟(模拟实现)和数据转换。所选择的支持SODA的工具必须支持这些重要概念(SODA的关键区分点),这一点很关键。下文将会描述这些区分点。

开箱即用的服务库——对于常见的企业应用程序功能(表示、业务和集成层)来说,必须存在一个现成的、功能广泛的服务库。这些服务还必须易于扩展和配置。

服务创建——显然,必须能够通过图形向导轻松创建服务。现有的或第三方组件应该能够通过工具轻松导出为服务。

服务组装(编排)——或许在开发人员生产力方面,最重要的就是在图形化的直观环境中,把服务组装(编排)为业务流程流的能力。这必须包括表示(页面/动作导航)和业务服务流。这里也需要声明性异常、安全性和事务划分。

服务库(关联到源控制)——一个集中式的服务库是必要的,它使用像UDDI这样的标准。通过工具把这个库关联到项目源控制系统的功能也是必需的,尽管这是通过外部工具(如:Ant)实现的。

查找和动态发现——服务库必须提供服务浏览、查找和动态运行时发现等功能。使用UDDI服务器作为库通常可以提供上述功能。

外部接口规范(WSDL或其他XML模式)——在SODA环境中,服务通常被公开为基于SOAP的Web services,该特性已经成为该标准的一个固有部分。工具应该为没有被公开为Web services的服务提供同样的功能。

服务转换(版本校正)——动态检测特定服务版本和该服务的客户端版本并提供二者之间的数据转换的能力,是必要的。

BEA WebLogic Workshop和其他工具

BEA WebLogic的Workshop (http://dev2dev.bea.com/wlworkshop/index.html) ISE很可能在(在J2EE环境中)对SODA提供支持方面是做得最全面的。它提供对关键区分点的支持,并允许对接口、接口编排和底层实现进行分离。在这方面无疑还有很多其他的工具。其中一些,比如Collexa的Web services编排产品,是免费赠送的,而且与Workshop集成得很好。其他的产品则直接参加竞争。Workshop有一些潜在的缺点:它当前支持的许多功能都将用户绑定到了BEA WebLogic平台上。许多功能已经被提交给Java Community Process,并被其接受为Java Specification Request (JSR)。借助于在Apache孵化器中发展良好的Beehive(蜂巢)计划,以及相关的Eclipse插件Pollinate,这里应该不存在厂商锁定(vendor lock-in)。“Bridging the Gap: BEA WebLogic Integration”一文(http://dev2dev.bea.com/pub/a/2004/05/Viarengo.html)详细说明了SODA上下文中的WebLogic Workshop。

图2 WebLogic Workshop控件抽象

概念验证(Proof of Concept,POC)

SODA在提高生产力方面具有很大的潜力。然而,它也有缺陷:

  • 缺乏工具支持方面的现行标准,这导致了一定程度的厂商锁定。
  • SODA把大量的开发负担放在工具上。这意味着工具必须能够熟练生成底层连接代码,这些代码或者完全向开发人员隐藏,或者在可用于定制时可以很容易地进行维护。
  • 最终得到的架构是不是可伸缩和高性能的?它是不是可扩展的?
  • 就所选择的SODA工具对开发人员进行训练需要付出大量的劳动。开发软件过程中的转变并不是无关紧要的。

 演示/证明一种SODA方法需要用到POC。该POC过程必须有足够的可扩展性,以便至少演示/证明以下概念:

  • 基于服务的设计范例转换。我们尤其需要深入了解各个服务层(至少实现/利用一个域、业务、用例和表示服务)。
  • 多团队开发。这包括源控制集成和SODA相关特定角色的指派(表示设计人员、用例设计人员、业务/域设计人员、J2EE专家、集成专家,等等)。
  • 一个实现了完整垂直片断的用例场景实现。这个用例场景涉及到所有层,(或许还特别)包括集成层,这一点很重要。
  • 组装和编排以下服务类型的演示:
    - 表示和表示流
    - 基本的Web services
    - 业务流程(工作流)
    - 消息收发
    - 后端集成(Back-end integration,EAI)
    - 安全性
  • 与底层J2EE组件的集成
  • 与现有功能的集成
  • 演示发布、随后的服务查找/发现,以及相关的元数据(文档)
  • 演示开发、构建、部署和发布这个周期
  • 演示服务模拟,以便显示对依赖性瓶颈的缓解

面向服务架构和域可插入性

本节讨论了SOA对更好地支持业务域可插入性的帮助程度。下面给出可插入性的定义。可插入性就是换出一种域实现(业务服务及相关域模型),然后使用另一种域实现来代替它。可插入性要求只能通过定义良好的接口(域的客户端,包括其他域,对接口以外的事情一概不知)来公开域实现。这可以使用基于组件的方法来实现;然而,这种方法具有局限性:域的客户端被绑定到特定版本的组件接口(至少不会通过反射/类加载器相关的循环进行跳转,或者使用某种脆弱的JNDI命名约定)。

通常,域模型太过于细粒度,以至于无法被直接公开为一组服务。因此,域模型中实现的任何域间关系都应该被最小化,以便为它的客户端(域服务)实现可插入性。这显然意味着,数据模型中的域间关系也要保持最小化。域模型只公开给域服务层。业务设备(如果需要)和用例服务层与域服务进行交互。域服务与它们的适用域模型进行交互,并把模型的细粒度的、面向对象的接口转换为粗粒度的、面向服务的接口。参见图3,您可以(通过例子)从概念上了解这些层是如何定义的。

图3 概念上的SOA分层

折衷

选择架构方法时总是要进行折衷,使用SODA的SOA方法当然也不例外。关于SOA(这个概念已经存在很多年了)和SODA的具体含义,有多种解释。在本文中,服务被定义为粗粒度接口(通常由工具生成,并且以XML编写)。这些服务可以(但是并不一定)被公开为Web services。这些服务应该在设计和运行时都是动态可配置的,这样我们才可以针对不同的目的重用某个特定的服务。

服务实现本身将会是定制构建和第三方的混合体。这些服务通常是分层的,而且在很大程度上会被编排成表示和业务流程。一旦谈到XML、分层和动态配置,就不可能不谈及性能和可伸缩性的问题。同样地,SODA对工具的巨大依赖性引发了对于厂商锁定的讨论。对特定工具集的依赖还引出了软件构建、修改管理、部署,以及这些工具如何与当前使用的基础架构互操作等方面的问题。

厂商锁定

SODA主要的价值在于工具支持表示和业务流程编排的方式、(几乎)无缝的XML/本地语言数据转换、设计/运行时服务配置、注册、发现,等等。这些都是在没有任何实际的、无所不包的SODA标准(当然,包含某一部分的标准是存在的,比如Web service/SOAP、BPEL/BPML、WS<fill-in-the-blanks>,等等)的情况下实现的。这保证了某种层次上的厂商锁定。厂商锁定的程度依赖于所选择的工具和这些工具的用法。

性能和可伸缩性

对于一个构建在基于XML的分层SOA上的应用程序来说,通常有很多影响它的性能的问题。这些问题与下列方面有关:使用像XML这样冗长的语言进行应用程序内部通信,客户端和服务都可能需要序列化和反序列化来把XML转换为本地的语言对象表示,这些都会带来潜在的开销。当更多的并发用户与应用程序交互时,就会带来更大的有效负载,这时候可伸缩性就开始起作用了。通过审慎地设计真正粗粒度的服务,只在定义良好的服务层之间进行通信,上述大部分问题都可以得到缓解。有限的长期状态确保了操作在适当的时候是异步的。通过优化XML转换(或者通过在它们的表示和业务流程流中本地操作XML),SODA工具通常可以减轻这个问题所带来的影响。但是最后肯定会带来更大的开销,而且在实际使用模式下,应用程序的性能分析必须更早地固定到流程中,以便确定哪里需要优化和调整。

构建、修改管理和部署

所挑选的工具必须可以与当前使用的基础架构互操作,或者具有能够轻松添加这种互操作能力的可扩展性。当前构建(通常是Ant)和源控制系统,以及标准的J2EE企业应用程序打包部署单元都是必需的。

结束语

真实情况是,使用基于SODA的最新工具构建的SOA无疑并非银弹,而实际上银弹是不存在的。通过数据/服务抽象和模拟,规范的SOA方法有助于在某种程度上缓解依赖性瓶颈的问题;然而,我们仍然必须对依赖性进行管理,尤其是在域层。另一方面,SOA的优点之一就是,由于服务和数据抽象,可以相对独立地开发高级服务。这也允许我们独立地开发表示和业务流程编排。

 

组织简介 | 联系我们 |   Copyright 2002 ®  UML软件工程组织 京ICP备10020922号

京公海网安备110108001071号