使用活动对象模型解决复杂业务事务的挑战

日期: 2008-09-03 作者:Mark M. Davydov 来源:TechTarget中国 英文

  了解如何在面向服务的体系结构(Service-Oriented Architecture,SOA)中使用活动对象模型(active object model)作为主要手段来设计所谓的以活动为中心的服务——这些服务是明确地为处理定义良好的任务或流程而设计的,并通过维护特定活动使用的所有应用程序的计算状态来完成其工作。以活动为中心的服务是用于支持复杂业务事务的基本构件。


  引言


  虽然面向服务的体系结构(Service-Oriented Architecture,SOA)——特别是Web服务——通常旨在支持广泛的消息交换模式,但是当今的现实是大多数生产实现都基于请求-响应和单向模式。诸如“信用卡授权”、“税款计算”、“获取项目”、“查找图书”、“检查股票”等简单的短时间请求-响应服务占据支配地位。


  出现这种情况的原因有几个。当然,其中之一是Web服务通常是使用不可靠的无状态传输协议(明确地说是HTTP)来实现的。但更重要的是,一些希望通过Web来执行复杂业务事务的公司对此问题采取了一种太“技术相关”的观点,并预期Web服务技术和相关供应商产品完全支持这样的工作。


  诸如OASIS等标准机构和诸如IBM、Microsoft、Oracle、BEA和等领先的SOA供应商认识到了处理所谓的“对话”消息交换模式的需要,该模式与Web服务实现中的实际业务事务(或操作系列,它们定义诸如按次序处理或保险报价处理等内聚的多步骤交互)等效。后来,出现了多个Web服务规范,例如WS-Addressing、WS-Resources和WS-Coordination以及WS-Transaction。而且最重要的是,业务流程执行语言(Business Process &#101xecution Language,BPEL)1.0规范已经整合了新的“WS-”标准建议的许多用于处理复杂业务事务的功能。然而,和许多与安全相关的Web服务标准不同,处理Web服务对话的新标准和相关供应商技术还没有得到广泛使用。此外,在当前版本中,BPEL本身在这个特定方面具有显著的缺点。


  同时,Web服务设计人员正在面临挑战,他们需要在更多类型的传输协议(例如,HTTP、SNMP等等)、更多类型的客户端设备上满足更多用户对Web上所有类型的实时交互的需要——例如,获取有关最合适产品的建议,而不只是在线购买商品。要应对此类挑战,将需要对服务(甚至是对那些服务的基础——它们的组件和对象模型)的设计进行日常维护。


  支持复杂业务事务的最有效方法之一是使用所谓的以活动为中心的服务——这些服务是明确地为处理定义良好的任务或流程而设计的,并通过维护特定活动使用的所有应用程序的计算状态来完成其工作。


  引入以活动为中心的服务和活动对象


  概括地说,以活动为中心的服务旨在执行单个活动,此活动涉及到许多不同的应用程序(或系统)和每个应用程序中的大量特定功能和数据表示形式。以活动为中心的服务的主要特征之一在于这些服务提供了执行保证,这不仅限于传统的ACID(原子性、一致性、隔离性和持久性)属性,并且可以包括时间上的约束、状态访问灵活性和多重交互的事务执行。这些保证不仅可能在应用程序之间有所不同,而且可能在一个应用程序中的不同事务之间也有所不同,具体取决于事务任务的属性、用户首选项和可用的系统资源。


  图1中的示例场景(搜索大量航班以查找最低票价的旅行预定服务)说明了这一点。在此示例中,客户端提供多组起飞和目的地信息,该服务搜索相关的航线以了解可用航班和票价。如果没有可用航班,则客户端与服务之间的交互必须停止。否则,该服务将向客户端返回航班和票价列表。然后,如果客户端从列表中选择某个特定航班,则该服务将要求客户端提供所需的私人信息以完成交易,例如姓名、地址和信用卡信息。此时,将执行若干任务。首先,将根据安全和信用卡授权规则验证所提供的信息,并在所提供的信息存在问题时通知客户端。如果所提供的私人信息可接受,则该服务将尝试预订航班。如果预订成功,则创建客户旅程记录,并向客户端返回该记录的标识符以便旅行者将来使用。



  图1. 示例场景——查找最低票价
 
  如果从计算的角度查看这里引用的示例,该服务实际上是在处理多个不同的应用程序:查询航线可用性、验证客户信息、预约航班、创建旅程等等。因此,您至少可以确定两个级别的服务抽象,即高级活动和由活动所操作的低级应用程序服务。我将这两个服务抽象级别分别表示为以活动为中心(业务)的级别和应用程序(离散)级别。从上面的示例中可以看到,以活动为中心的服务引入了多个关键技术要求,特别是:


  ·服务上调用的进程密集型方法不应该阻塞整个进程。
  ·对共享资源的同步访问应该允许透明的序列化和调度。
  ·服务应该设计为利用并行性(例如,在该示例中,可能存在数千个需要快速搜索的航班地点)。


  首先,“以活动为中心的服务”的概念是在活动服务框架(Activity Service Framework)规范中定义的,OMG为响应自己对用于对象事务服务(Object Transaction Service,OTS)的专门结构化机制的号召而提交了该规范。最近,这个概念正在重新引入网格计算领域。这里,规定了附加的技术要求,包括


  ·以活动为中心的服务应该能够响应异步事件(例如,动态地向事务添加新的参与方的能力;例如,可能需要自动监视客户在基于Web的店面上的会话,并通过允许客户代表加入交互过程来主动进行干预)。
  ·在组合以活动为中心的服务时,组合引擎必须能够接收异步事件,并确定如何和是否在服务组合中影响参与者(此功能是BPEL引擎的最重要功能之一)。
  ·以活动为中心的服务的基础结构必须支持服务之间跨越时间和空间的通信和协作。


  因此,以活动为中心的服务的通用对象模型已通过以下代码行浮现出来:


  清单1. 以活动为中心的服务对象模型


  public interface Activity {
      public ActivityId &#101xecute(ActivitySpecification actSpec,
                          ClientSpecification clientSpec,
                          RemoteEventListener callback)
          throws RemoteException, ActivityException;
      // other methods …


  人们建议了许多对象模型来实现以活动为中心的服务,其中最有趣的是活动对象模型。遗憾的是,该模型的几个问题阻止了它在商业环境中的广泛采用。首先,有些人对活动对象究竟是什么感到混淆;基本上,四处流传着活动对象的太多不同定义。其次,有些所谓的“SOA专家”正在鼓吹“用于分布式对象的活动对象模式超出了Web服务的功能”。实际上,此类观点言过其实。诚然,实现活动对象需要费一番工夫,但是这样的对象支持构建并发应用程序,此类应用程序将在不断发展的SOA运动中高度适用。业界已从紧密耦合的RPC风格的同步服务转向松散耦合的异步服务。


  Grady Booch于1990年在其有关面向对象的应用程序设计的书中最先引入了活动对象。他将活动对象定义为具有自己的控制线程(或自己为自己提供支持)的对象。从那以后,活动对象在Java移动版本和实时嵌入开发中赢得了大量的立足之地。然而,使用它们来实现大规模电子商务应用程序中的对话Web服务同样可以成功。对于这些用途,首先应该将活动对象明确视为能够并发运行的对象(相对于作为服务的一部分来运行的其他对象而言),其次(并且最重要的是),活动对象能够在与某个客户端相关的整个生命周期过程中维护服务的内部状态。此外,活动对象能够通过组合关系来聚合被动对象。


  就实现而言,活动对象符合以下形式:


  清单2. 以活动为中心的服务对象类


  class ActiveObject implements Runnable { private Thread activity;
  public ActiveObject() {
  activity = new Thread(?);
  activity.start();
  }
  public void run() { … }
  }
 
  虽然从结构上讲,可以存在多种活动对象表示形式,但是在本文的上下文中,最适当的是包括以下七个组件的模型(如图2所示):


  ·Requester或Proxy——提供用于调用活动对象上的方法的接口。
  ·Servant——实现与请求者的接口和请求者创建的方法请求相对应的活动对象。
  ·Method Request——包含诸如参数等上下文信息,并表示对活动对象的方法调用。
  ·Activation Queue——维护等待执行的方法请求。
  ·Future——存储活动对象上的方法调用的结果。
  ·Scheduler——将方法请求插入激活队列。
  ·State Machine——描述活动对象的行为。



  图2. 活动对象模型——类关系图
 
  本文已非常深入地讨论了这个话题,下面让我们重申一下到目前为止已看到的难点:


  首先,当我们在SOA中处理活动对象的时候,体系结构范式是一项策略,其基于“面向服务的系统具有两个不同部分”的概念:面向对象和面向服务的模型。


  面向对象的模型将系统定义为一组交互的主动和被动对象的集合。这些对象包含系统的功能和数据。然后,在面向对象的模型基础上建立了面向服务的模型,其中活动对象变为网络化的对象,它们扮演预定义的服务请求者或服务提供者角色。服务提供者是接受来自服务请求者的消息以执行某项工作(某个任务或活动)的对象。


  其次,由于以下原因,活动对象从长期的角度来看对SOA特别有吸引力:


  ·它们解决了大规模分区和并发问题。
  ·它们根据需要进行通信以完成工作,按自己的计划封装了要做什么、如何做以及何时做,并带有清楚的“从运行到完成的工作方式”语义。
  ·它们高度模块化,非常易于调度。


  用于实现活动对象的实用方法


  存在多种使用活动对象来实现以活动为中心的服务的方法。其中,最简单和相当有效的方法如图3所示。



  图3. 实现示例——结构
 
  图3引用的方法具有三个不同的部分:处理消息的服务访问层(SAL)、提供服务分派和管理的服务管理层(SML),以及业务对象层(BOL)。SAL和SML都实现了一个活动对象模型。实现为EJB的业务对象扮演被动对象的角色。将被动对象实现为EJB是首选的,因为它为服务提供好得多的可用性和可伸缩性特征。


  此时,我将重点介绍用于实现活动对象模型的特定设计技术。遗憾的是,由于空间所限,我将仅介绍与本文主题相关的最重要元素。


  您可以使用Apache Axis框架来构建SAL。这里,我假设您对Axis体系结构和Axis的工作方式具备基本的了解。


  通过选择Axis,处理消息和使用消息来互连活动对象就变得容易多了。Axis提供了许多重要的功能,包括处理程序、链、序列化器和反序列化器。它允许创建适当的MessageContext,并通过一组已配置的处理程序将MessageContext传入invoke()方法,其中每个处理程序可以对MessageContext执行必要的逻辑。


  在实现活动对象模型时涉及到的最重要处理程序类型是提供程序处理程序。提供程序是处理传入请求的特殊Axis处理程序。Axis提供了许多不同的提供程序。可以在部署新服务时指定应该对给定的Web服务使用哪一个提供程序。Axis的提供程序模型是可扩展的,从而意味着您可以插入自己的自定义提供程序。清单3显示了用于将服务部署到Axis中的典型WSDD文件。它表明某个自定义提供程序将处理传入请求:


  清单3. Axis WSDD部署示例


  <deployment
        >
  <service name=”LowestFareService” provider=”java:LowestFareProvider” />
  </deployment>”
   
  如图3所示,可以构造提供程序来扮演实现Runnable接口的异步调用处理程序的角色。该接口使用run()方法在处理程序的控制线程中处理各个请求。此外,提供程序将所有必要的信息放入新的EventMessage中,后者被传递给SML的入口点Manager。EventMessage将有关调用处理程序上的特定服务调用的上下文信息(例如方法参数和代码)从处理程序传递到在单独线程中运行的Manager。


  事件类型的消息不应该包含任何特定于SOAP的数据。这样允许将活动对象的实际实现与Axis和SOAP协议分离。


  如图3所示,一旦接收到来自Manager的回调,提供程序将创建一个新的SOAP响应消息,此响应消息重新回到Axis响应流,并最终从那里被发送回调用服务的客户端。回调功能是提供者的最重要功能之一。它取得作为消息进行传递的onFuture()方法的结果(请参见图4的讨论),并将其转换为SOAPMessage实例。


  图4是协作关系图,其中给出了SML中涉及到的最重要类的粗略图形表示形式:


  ·Manager——扮演活动对象模型的代理角色;通过使用EventMessage的实例,Manager确定放入激活队列中的服务调用请求。此队列跟踪要执行哪些服务请求。
  ·Dispatcher——管理等待执行的服务请求的激活队列;它决定接下来哪个请求退出队列并在实现该请求的Service Delegate对象上执行。
  ·Service Delegate——封装对EJB的访问,类似于Sun的J2EE Blueprints所引入的Business Delegate模式;定义被建模为活动对象的行为和状态;Service Delegate在Dispatcher执行对应的服务请求时被调用。
  ·Future——允许Manager在Service Delegate完成执行后获得服务调用的结果;Future为EJB调用的结果保留空间。



  图4. 实现示例——协作关系图
 
  Activation Queue是一个事件处理类型的队列,它可以收集来自多个提供者的事件。Dispatcher按先进先出(FIFO)的顺序分派事件。可以使用向量来实现此队列,但是更高效的实现是使用链表或管道流。为了将到达的服务请求放入队列中,Manager实现了pushRequest()方法,如下所示:


  public synchronized void pushRequest(Object eventMessage);


  pushRequest()可以定义到达的事件是否要由某个回调方法进行处理。如果是,则调用replyImmediate(),否则,将到达的事件压入队列。此外,Manager调用notify()以唤醒服务委托的线程,以便能够处理到达的事件。然后,它必须等待使用关联的服务委托对象的结果来填充所有的Future,但这是在后台进行的。此外,Manager可以在内部实现某种类似如下的等待循环:


  清单4. 等待循环示例


  public synchronized Object get() {
    while(futureResult==null) wait();
    return futureResult;
  }
   
  结束语


  您可能忍不住匆忙地给本文下结论——也许是认为“您在这里倡导的是一种专有设计,而不是集中于BPEL!”毫无疑问,使用BPEL是以活动为中心的服务的“最容易”实现方法。但是今天的BPEL技术尚处于成熟周期的开头。它们还没有为处理某些类型的复杂、大规模应用程序(例如本文中的最低航班票价服务)做好准备。活动对象模型是可行的备选方法吗?我强烈地认为是这样,并且基于本文中介绍的此类模型的策略是用于在企业中和在企业之间连接支持Web服务的应用程序的关键,并具有一组支持对连接的应用程序之间的交互进行管理和监视的功能。


  关于作者


  Mark M. Davydov博士是国际知名的软件工程和系统体系结构(包括SOA)专家。Davydov博士在与计算机相关的出版物上发表了许多受到高度赞扬的文章。他在2001年出版的图书Corporate Portals and e-Business Integration–A Manager’s Guide(McGraw-Hill Professional Publishing出版)中介绍了许多影响面向服务的体系结构和Web服务模型发展进度的思想。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • SAP收购CallidusCloud 与Salesforce竞争

    一直被称为后台办公巨头的SAP现在似乎也想在前台办公大展拳脚。 最新的迹象是SAP收购CallidusClou […]

  • 联合创新,携手共赢 华为与Commvault签署全球合作联盟协议

    【中国,上海,2015年9月19日】在2015年华为云计算大会上,全球领先的信息与通信解决方案供应商华为与美国知名的数据管理软件及相关服务主要供应商Commvault签署全球合作联盟协议。基于合作协议,双方将会加大投入数据中心备份解决方案在云化环境下的“可服务化”技术研究 。Commvault公司全球业务发展副总裁Andreas May、华为IT数据中心解决方案总裁马力出席签约仪式。

  • API设计如龙生九子 各不相同

    IT咨询管理公司CA Technologies对API产业做了个问卷调查,问卷内容涉及API设计风格以及管理部署的新动向。调查结果表明,JSON与XML可谓两分天下。

  • 保险公司如何能从BPEL中获益

    对于保险业整合不同系统是一件寻常的工作。但保险公司经常会面临监管条例改变和应对不同的顾客需求。为了解决这些系统问题,软件专家正在使用一种强大的工具——BPEL。