Activiti并行服务任务

问题描述 投票:1回答:1

我试图在Activiti中实现两个应该并行运行的服务任务。下面编写的代码随机(并且有趣)工作得很好。

我的意思是,它偶尔只打印“first”(或“second”)或它打印两个“first”一个“second”等。

问题:如何使这些服务不断并行运行;无论目前运行的服务数量是多少?

PS:当我从流程定义中删除activiti:async="true"时,它只打印“first”或“second”。我想我需要:)

流程定义

<?xml version='1.0' encoding='UTF-8'?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn" targetNamespace="Examples">

    <process id='testparallelact' name="Developer Hiring" isExecutable="true" activiti:exclusive="false" activiti:async="true">

        <startEvent id="theStart" />
        <sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

        <parallelGateway id="fork"  activiti:async="true" />
        <sequenceFlow sourceRef="fork" targetRef="receivePayment" />
        <sequenceFlow sourceRef="fork" targetRef="shipOrder" />


        <serviceTask id="receivePayment" name="Receive Payment" activiti:async="true" activiti:exclusive="false"
activiti:expression="${serviceConnections.runThis2('First')}"/>

        <sequenceFlow sourceRef="receivePayment" targetRef="join" />


        <serviceTask id="shipOrder" name="Ship Order" activiti:async="true" activiti:exclusive="false"
activiti:expression="${serviceConnections.runThis2('Second')}"/>

        <sequenceFlow sourceRef="shipOrder" targetRef="join" />

        <parallelGateway id="join" />
        <sequenceFlow sourceRef="join" targetRef="theEnd" />
        <endEvent id="theEnd" />
    </process>
</definitions> 

Graphical rendering of process definition

Graphical rendering of process definition

“runThis2”的代码

public void runThis2(String test1) throws InterruptedException {            
    while(true)
    {
        Thread.sleep(1000);
        System.out.println(test1);              
    }           
}
java activiti
1个回答
3
投票

Combination of "async" and "exclusive" flags matters

了解如何在Activiti引擎内执行作业非常重要。以下论坛帖子可以很好地描述它:

https://community.alfresco.com/thread/221453-multiinstance-wont-run-task-in-parallel

2013-10-25,一位最初的Activiti建筑师Tijs Rademakers的重要摘录:

例如,并行网关和多实例构造能够并行运行多个用户任务。但是对于服务和脚本任务,它们基本上仍然是串行执行的。如果您还将exclusive设置为false(默认值为true),则Async可以更改此行为。然后,作业执行程序将只执行所有可用作业而不是连续执行。因此,尝试将async设置为true,将exclusive设置为false。

现在,通过设置activiti:async="true"activiti:exclusive="false",您有效地完成了通过将服务任务(通常是串行处理)分配给Job Executor来在过程中创建“等待状态”。

但:

  • 并行执行多少个作业
  • 当它们由Job Scheduler执行时

现在完全由Job Executor配置控制。 (线程池的大小,超时,并发作业的数量,作业块的大小都是可配置的。)

现在,这并不完全符合您的预期,这意味着,它取决于作业队列的大小,单次扫描中占用的作业数以及每个作业执行服务任务的持续时间。意思是,它们可以并行执行,它们可以连续执行。同样,您无法控制他们的订单,因为Job Executor会再次确定它的作用和时间。

好的,假设这符合您的要求......

Optimistic Locking concept

......还有一个问题可能会遇到(实际上,这就是activiti:exclusive旗帜首先被引入的原因)。完成服务任务后,执行上下文将提交到数据库中的流程实例记录以及历史记录。 Activiti使用“乐观锁定”来记录性能。

现在,如果你的进程分支在时间上彼此相对接近完成,那么有可能(实际上很有可能)你将在数据库更新中收到Optimistic Locking Exception,如下所示:

09:59:52,432 [flowable-async-job-executor-thread-2] ERROR org.flowable.job.service.impl.asyncexecutor.DefaultAsyncRunnableExecutionExceptionHandler - Job 12575 failed org.flowable.engine.common.api.FlowableOptimisticLockingException: ProcessInstance[12567] was updated by another transaction concurrently

(注意:上面的错误实际上不是来自Activiti,而是来自一个名为“Flowable”的项目。但是,在最初询问这个问题的时候,它们都与Activiti 6具有基本相同的代码库。(2017年11月)。)

这将导致服务任务被标记为FAILED并将重新尝试。如果要对SOR(记录系统)或其他遗留系统进行外部调用,则可能会出现问题。 (考虑一下如果您的航班实际成功预订会发生什么,但保留它的呼叫是第二次,因为它被认为已经失败。)

所有好玩的东西和所有可以通过良好的设计和使用最佳实践来解决的事情。

希望这可以帮助您了解正在发生的事情。

格雷格@ BP3

进一步阅读

Alfresco论坛帖子包含几个死链接。以下是实时链接。

Dead Issue Tracker links

附加说明:Activiti目前(2019)不再使用这两个(codehaus.org或atlassian.net)跟踪器。相反,他们使用这个GitHub跟踪器:https://github.com/Activiti/Activiti/issues

Dead FAQ link

Activiti flags

Camunda Manual

© www.soinside.com 2019 - 2024. All rights reserved.