第 10 章  异步约定


10.1. Concept

Dan 基于 Graph-Oriented 编程 (GOP)。基本上,GOP 指定一个简单的状态计算机,它可以处理执行的并发路径,但在指定的执行算法中,所有状态转换都会在单个线程客户端操作中进行。默认情况下,这是在客户端的线程中执行状态转换的好方法,因为它适用于服务器端事务。进程执行从一个"等待"状态移到一个事务空间中的另一个状态。
在某些情况下,开发人员可能希望微调进程定义中的事务。在 jPDL 中,可以指定进程执行应该与属性 async="true" 异步继续。async="true" 仅在事件中触发但可在所有节点类型和所有操作类型中指定时才支持。

10.2. 示例

通常,节点总是在令牌输入后执行。因此,节点会在客户端的线程中执行。一个将通过查看两个示例来探索异步持续情况。第一个示例是具有三个节点的进程的一部分。节点 'a' 是一个等待状态,节点 'b' 是一个自动步骤,节点 'c' 是等待状态。这个过程不包含任何异步行为,在下图中表示。
第一个帧显示启动情况。令牌指向节点 'a',这意味着执行的路径正在等待外部触发器。该触发器必须通过向令牌发送信号来提供。当信号到达节点时,令牌将通过转换到节点"b"从节点"a"传递。在令牌到达节点 'b' 后,执行节点 'b'。重试该节点 'b' 是一个自动步骤,它不充当等待状态(例如发送电子邮件)。因此,第二个帧是在执行节点"b"时进行的快照。由于节点 'b' 是进程中的一个自动步骤,节点 'b' 的执行将包括向节点"c"传播令牌。节点 'c' 是一个等待状态,因此第三个帧在信号方法返回后会显示最终情况。

图 10.1. 示例 1:没有异步协调的进程

Whilst "persistence" 并不强制使用,通常在事务中调用信号。查看该事务的更新。最初,令牌被更新以指向节点 'c'。这些更新由 Hibernate 在 JDBC 连接上生成,因为 GraphSession.saveProcessInstance。其次,如果自动操作访问和更新某些事务资源,则此类更新应合并或在同一事务的一部分。
第二个示例是第一个变体,并在节点 'b' 中引入了异步延续。节点"a"和"c"的行为与第一个示例的行为相同,即它们的行为与等待状态相同。在 jPDL 中,通过设置属性 async="true" 来标记为异步节点。
async="true" 添加到节点 'b' 的结果是,进程执行将分为两个部分。其中的第一个将执行进程,直到要执行节点"b"的时间。第二部分将执行节点 'b'。 该执行将停止等待状态 'c'。
因此,事务将分成两个独立的事务,每个事务对应一个。虽然它需要一个外部触发器(调用 Token.signal 方法)来离开第一个事务中的节点"a",但 lsblk 将自动触发并执行第二个事务。

图 10.2. 具有异步一致性的进程

对于操作,原则类似于。带有属性 async="true" 的操作是在执行进程的线程外执行的。如果配置了持久性(默认为 ),则操作将在单独的事务中执行。
在 Dan 中,异步持续使用异步消息传递系统来实现。当进程执行过程在应异步执行的时间到达时,Chef 将挂起执行,生成命令消息并将其发送到命令执行器。命令 executor 是一个单独的组件,在收到消息时,将恢复暂停进程的执行。
xmvn 可以配置为使用 JMS 提供程序或内置的异步消息传递系统。内置的消息传递系统在功能方面有限,但允许在 JMS 不可用的环境中支持此功能。

10.3. 作业执行者

作业执行程序是 异步恢复进程执行的组件。它会等待作业消息到达异步消息传递系统并执行它们。用于异步延续的两个作业消息是 ExecuteNodeJobExecuteActionJob
这些作业消息由进程执行生成。在进程执行期间,对于必须异步执行的每个节点或操作,作业 (旧 Java 对象)将被分配给 MessageService。消息服务与 JbpmContext 关联,它只收集必须发送的所有消息。
消息将作为 JbpmContext.close () 的一部分发送。此方法会对所有相关服务的 close() 调用进行级联。实际的服务可以在 jbpm.cfg.xml 中配置。默认情况下,其中一个服务 JmsMessageService 配置,并通知作业执行器新的作业消息可用。
图形执行机制使用接口 MessageServiceFactoryMessageService 来发送消息。这是使异步消息服务可配置(也位于 jbpm.cfg.xml中)。在 Java EE 环境中,DbMessageService 可以替换为 JmsMessageService,以利用应用服务器的功能。
以下是作业执行器工作方式的简短总结。
"jobs"是数据库中的记录。此外,它们是对象,可以执行。计时器和异步消息都是作业。对于异步信息,dueDate 只需在插入时将其设置为当前时间。作业执行器必须执行该作业。这分为两个阶段。
  • 分配程序线程必须获得一个作业
  • executor 线程必须执行该作业
获取作业并执行作业是在 2 个独立的事务中进行的。分配程序线程代表此节点上的所有 executor 线程从数据库获取作业。当 executor 线程使用作业时,它会将其名称添加到作业的 owner 字段中。每个线程都有一个基于 IP 地址和序列号的唯一名称。
线程可能会在作业参与和执行之间失败。要在这些情况后进行清理,每个作业执行器都有一个锁定的线程来检查锁定时间。锁定监控线程将解锁任何已锁定超过 10 分钟的作业,以便它们可以由另一个作业执行器线程执行。
隔离级别必须设置为 REPEATABLE_READ,以便 Hibernate 的选择锁定正常工作。REPEATABLE_READ 保证此查询只会更新其中一个销售事务中的一行。
update JBPM_JOB job
set job.version = 2
    job.lockOwner = '192.168.1.3:2'
where 
    job.version = 1
Copy to Clipboard Toggle word wrap
不可重复读取可能会导致以下异常:事务重新读取之前已读取的数据,并发现数据已被另一个事务修改,它是自事务之前读取以来提交的事务。
不可重复读取是最佳锁定的问题,因此隔离级别 READ_COMMITTED 不足,因为它允许出现不可恢复的读取。因此,如果您配置多个作业执行器线程,则需要 REPEATABLE_READ
与作业执行器相关的配置属性有:
jbpmConfiguration
从中检索配置的 bean。
name
此 executor 的名称。
重要
当在一台机器上启动多个 实例时,此名称对于每个节点都是唯一的。
nbrOfThreads
启动的 executor 线程数量。
idleInterval
如果没有任务待处理,在检查作业队列前,分配程序线程将等待的时间。
注意
当作业添加到队列中时,分配程序线程会自动通知。
retryInterval
如果在执行过程中失败,作业会在重试之间等待的时间。此值的默认值为 3 次。
注意
重试的最大次数由 jbpm.job.retries 配置。
maxIdleInterval
idleInterval 的最大周期。
historyMaxSize
此属性已弃用,无效。
maxLockTime
在 lock-monitor 线程解锁前可以锁定作业的最长时间。
lockMonitorInterval
lock-monitor 线程在检查锁定的作业之间的休眠时间。
lockBufferTime
此属性已弃用,且不会影响。

10.4. Ice 的内置异步消息传递

在使用 lsblk 的内置异步消息时,将把作业消息保留给数据库来发送。此消息持久可以在与 jBPM 进程更新相同的事务或 JDBC 连接中完成。
作业消息将存储在 J114 _JOB 表中。
POJO 命令 executor (org.jbpm.msg.commandExecutor)将从数据库表中读取消息并执行它们。POJO 命令执行器的典型事务类似如下:
  1. 读取下一个命令消息
  2. 执行命令消息
  3. 删除命令消息
如果执行命令消息失败,事务将回滚。之后,将启动一个新的事务,将错误消息添加到数据库中的消息。命令 executor 过滤掉包含异常的所有消息。

图 10.3. POJO 命令执行器事务

如果向命令消息添加异常的事务失败,则会回滚。该消息将保留在队列中,没有例外,之后将被重试。
重要
Ice 的内置异步消息传递系统不支持多节点锁定。您不能多次部署 POJO 命令执行器,并将其配置为使用同一数据库。
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat