繁体   English   中英

Activiti并行服务任务

[英]Activiti parallel Service Tasks

我正在尝试在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> 

流程定义的图形呈现

流程定义的图形呈现

代码为“ runThis2”

public void runThis2(String test1) throws InterruptedException {            
    while(true)
    {
        Thread.sleep(1000);
        System.out.println(test1);              
    }           
}

“异步”和“排他”标志的组合很重要

了解作业如何在Activiti引擎内执行非常重要。 以下论坛线程在描述它方面做得很好:

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

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

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

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

但:

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

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

现在,这并不完全符合您的期望,这取决于您的作业队列的大小,一次扫描中有多少个作业以及每个作业的执行时间以及执行服务任务的时间。 意思是,它们可能并行执行,并且可能串行执行。 同样,您无法控制他们的订单,因为再次由求职执行者来决定其工作和时间。

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

乐观锁概念

...您可能还会遇到另一个问题(实际上,这是首先引入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论坛帖子包含几个无效链接。 以下是实时链接。

遗留问题跟踪链接

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

常见问题解答链接

Activiti标志

卡蒙达手册

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM