jBPM用户指南 第十三章 异步继续 (转载)

来源:互联网 发布:nginx 反向代理优化 编辑:程序博客网 时间:2024/04/28 02:07
第13章 异步继续
13.1 概念
jBPM以面向图的编程(GOP)为基础,从基本上来讲,GOP指定了一个可以处理当前执行路径的简单状态机。在GOP中指定的执行算法中,所有状态的转换在客户端线程的一个单一操作中完成,如果你不熟悉在“第4章 面向图的编程”中定义的执行算法,请先阅读该部分。默认情况下,在客户端线程中完成状态转换是一个不错的方法,因为它自然地与服务端的事务保持一致,流程从一个等待状态到另一个等待状态的执行在一个事务中完成。
但是在某些情形开发者或许想在流程定义中调整事务划分。在jPDL中,可以使用属性async=“true”指定流程执行以异步的方式继续,可以在任何节点类型和动作类型上指定async=“true”。
13.2 一个实例
通常,节点总是在令牌进入之后被执行,因此,节点在客户端线程中被执行。我们将通过两个例子来研究异步执行,第一个例子有三个节点,它是一个流程的部分,节点“a”是一个等待状态,节点“b”是一个自动化步骤,节点“c”也是一个等待状态,下面的图中表现了这个流程不包含任何异步行为的情形。
第一个框图中展示了开始情形,令牌指向节点“a”,意味着执行路径正在等待一个外部的触发器,触发器必须通过发送一个信号到令牌引起。当信号到达时,令牌将被从节点“a”通过转换被传递到节点“b”,令牌到达节点“b”之后, 节点“b”被执行。回想一下,因为节点“b”是一个自动化步骤,它不会作为一个等待状态(例如发送一个email),所以第二个框图只是当节点“b”被执行时的一个快照,因为节点“b”是流程中的一个自动化步骤,所以节点“b”的执行包含了令牌通过转换到节点“c”的传播。节点“c”是一个等待状态,因此第三个框图展示了signal方法返回后的情形。
13.1 例1:没有异步继续的流程
虽然在jBPM中持久化不是必须的,但是通常情况下信号在一个事务中被调用。让我们看一下该事务的更新,首先,令牌被更新为指向节点“c”,这些更新作为GraphSession.saveProcessInstance的结果被hibernate在一个JDBC连接上发生;其次,如果自动化动作访问和更新某些相互影响的资源,那些资源的更新会与上述事务组合或作为事务的一部分。
现在我们看一下第二个例子,第二个例子是第一个例子的变种,在节点“b”引入了一个异步执行,节点“a”和“c”的行为表现与第一个例子中相同,也就是它们表现为等待状态。在jPDL中,一个节点通过设置属性async=“true”来标识为异步。
添加async=“true”到节点“b”的结果就是流程的执行将被分裂为两部分。一部分将执行流程直到节点“b”被执行;另一部分将会执行节点“b”,并且执行在等待状态“c”停止。
事务因此也将被分裂为两个独立的事务,每个事务对应于一部分。当在第一个事务中需要一个外部触发器(Token.signal方法调用)来离开节点“a”时,jBPM将会自动触发并完成第二个事务。
13.2 例2:有异步继续的流程
对于动作(action)原理相似,被属性async=“true”标识的动作在执行流程的线程之外被执行,如果持久化被配置(这是默认的),则动作在一个独立的事务中被执行。
在jBPM中,异步执行通过使用一个异步通知系统来实现。当流程执行到达需要异步执行的点时,jBPM将挂起执行,产生一个命令消息并发送该命令消息到命令执行器,命令执行器是一个单独的组件,在收到的消息之上它将在流程挂起的地方恢复流程执行。
jBPM可以被配置为使用JMS提供者或者它自己内置的异步通知系统,内置的通知系统在功能上是很有限的,但是可以在JMS不能使用的环境中支持异步特性。
13.3 命令执行器
命令执行器是恢复流程异步执行的组件,它通过异步通知系统等待命令消息的到达并执行它们,ExecuteNodeCommand和ExecuteActrionCommand两个命令被用来异步继续。
这些命令由流程执行产生,在流程执行过程中,对于每个需要异步执行的节点,一个ExecuteNodeCommand(POJO)将被在MessageInstance(消息实例)中创建,消息实例是ProcessInstance的一个非持久化扩展,它只是用来聚集所有将要发送的消息。
消息将被作为GraphSession.saveProcessInstance的一部分被发送,该方法的实现包含一个上下文构建器,构建器作为saveProcessInstance方法的一个方面(aspect)。实际使用的拦截器可以在jbpm.cfg.xml中配置,SendMessagesInterceptor拦截器被默认配置,用来从MessageInstance中读取消息并且通过可配置的异步通知系统发送消息。
SendMessagesInterceptor使用接口MessageServiceFactory和MessageService发送消息,这使得异步通知实现是可配置的(也是在jbpm.cfg.xml中)。
13.4 jBPM内置的异步消息
当使用jBPM内置的异步通知时,消息通过持久化到数据库被发送,消息的持久化可以与jBPM流程更新一样在同一个事务、jdbc连接中完成。
命令消息将被存储在JBPM_MESSAGE表中。
POJO命令执行器(org.jbpm.msg.command.CommandExecutor)将从数据库表中读取消息并执行它们,因此POJO命令执行器典型的事务处理如下:1)读取下一个命令消息2)执行命令消息3)删除命令消息。
如果命令消息执行失败,事务将会回滚,然后一个新的事务将被开始用来添加错误信息到数据库的消息,命令执行器过滤掉所有包含异常的消息。
13.3 POJO命令执行器事务
如果由于某些原因添加异常到命令消息的事务失败了,它也一样会被回滚,在这种情况下,没有异常的消息依然被保留在队列,因此它将在以后被再次尝试执行。
局限性:jBPM内置的异步通知系统不支持多个节点同步,因此你不能多次配置POJO命令执行器并且把它们配置为使用相同数据库。
13.5 JMS用于异步结构
异步执行特性打开了jBPM所适用场景的一个新局面,典型的被用在业务流程建模时,它可以从一个非常技术的观点来使用。
设想你有一个拥有很多异步处理的应用,绑定所有的消息生成和消息销毁软件在一起是很困难的,如果使用jBPM这将成为可能。通过创建所有异步结构的视图,把你的所有代码放入POJO,并且在流程文件中添加事务划分,就可以做到了。jBPM考虑到了你无需自己编写所有JMS或MDB代码而绑定发送者到接受者。
13.6 JMS用于异步通知
TODO(还未实现)
13.7 未来趋势
TODO:添加支持多个队列,因此可以为每个标识为异步的节点或动作指定一个队列,并且将循环为一组队列生成消息。因为所有这些对于JMS和内置的通知系统将是可配置的,所以对于怎样处理所有这些配置需要一些考虑。流程定义将无需依赖于这两个可能的实现。 
原创粉丝点击