第13章. 异步延续

第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方法返回后的情形。

Example 1: Process without asynchronous continuation

图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将会自动触发并完成第二个事务。

Example 2: A process with asynchronous continuations

图 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)删除命令消息。

如果命令消息执行失败,事务将会回滚,然后一个新的事务将被开始用来添加错误信息到数据库的消息,命令执行器过滤掉所有包含异常的消息。

POJO command executor transactions

图 13.3. POJO命令执行器事务

如果由于某些原因添加异常到命令消息的事务失败了,它也一样会被回滚,在这种情况下,没有异常的消息依然被保留在队列,因此它将在以后被再次尝试执行。

局限性:jBPM内置的异步通知系统不支持多个节点上锁,因此你不能多次配置POJO命令执行器并且把它们配置为使用相同数据库。

13.5. JMS用于异步架构

异步延续特性打开了jBPM所适用场景的一个新局面,典型的被用在业务流程建模时,它可以从一个非常技术的观点来使用。

设 想你有一个拥有很多异步处理的应用,绑定所有的消息生成和消息销毁软件在一起是很困难的。如果使用jBPM通过创建所有异步架构的视图这将成为可能。把你 的所有代码放入POJO,并且在流程文件中添加事务划分,就可以做到了。jBPM考虑到了你无需自己编写所有JMS或MDB代码而绑定发送者到接受者。

13.6. JMS用于异步消息

TODO (未实现)

13.7. 未来趋势

TODO:添加支持多个队列,以便可以为每个标识为异步的节点或动作指定一个队列,并且将循环为一组队列生成消息。因为所有这些对于JMS和内置的通知系统将是可配置的,所以对于怎样处理所有这些配置需要一些考虑。流程定义将无需依赖于这两个可能的实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值