提问者:小点点

Activiti并行服务任务


我正在尝试在Activiti中实现两个应该并行运行的服务任务。下面编写的代码可以很好地随机运行(并且有趣)。

我的意思是它偶尔只打印“first”(或“第二个”)或打印两个“first”one“第二个”等。

问:如何让这些服务持续并行运行;不管当前运行的服务数量如何?

PS:当我从进程定义中删除tiviti: async="true"时,它只打印了"first"或"第二"。我想我需要那个:)

<?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> 

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

共1个答案

匿名用户

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

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

2013年10月25日,Activiti原始建筑师之一Tijs Raddaker的关键摘录:

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

现在,通过设置活动:async="true"活动:独占="false",您实际上所做的是通过将服务任务(通常串行处理)分配给作业执行器来在流程中创建“等待状态”。

但是:

  • 有多少作业并行执行和
  • 当它们被作业调度器执行时

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

现在,这不是你所期望的,意思是,这取决于你的作业队列的大小,一次扫描中有多少个作业,以及每个作业的持续时间,以及何时执行服务任务。也就是说,它们可能会并行执行,也可能会串行执行。同样,你不能控制它们的顺序,因为它们又一次在作业执行器上决定它做什么和何时执行。

好吧,假设这符合你的要求…

…还有一个你可能会遇到的问题(事实上,这就是最初引入tiviti:独占标志的原因)。服务任务完成后,执行上下文将提交到数据库中的流程实例记录以及历史记录中。出于性能目的,Activiti对记录使用“乐观锁定”。

现在,如果您的进程分支在时间上彼此相对接近地完成,那么您可能(实际上极有可能)会在DB更新时收到乐观锁定异常,如下所示:

09:59:52,432[flow able-async-job-expator-thread-2]ERROR org.flow.job.service.inl.asyncexector.DefaultAsyncRunnableExecutionExceptionHandler-Job 12575失败org.Flow able.engine.公共.api.FlowableOpenticLockingException:ProcessInstance[12567]被另一个事务并发更新

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

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

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

希望这能帮助你理解正在发生的事情。

Greg@BP3

阿尔弗雷斯科论坛帖子包含几个死链接。下面是实时链接。

  • 死亡:http://jira.codehaus.org/browse/ACT-1814=
  • 活着:https://activiti.atlassian.net/browse/ACT-2126

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

  • 死亡:http://activiti.org/faq.html#WhatIsTheDifferenceBetweenProcessConcurrencyAndJavaConcurrency=
  • 激活:异步标志:https://www.activiti.org/userguide/#asyncContinuations
  • 活动:独占标志:https://www.activiti.org/userguide/#exclusiveJobs
  • 开发人员Joram Barrez对使用活动的评论:async="true"with活动:独占="false"
    • 死亡:https://community.alfresco.com/thread/220483-what-is-activitiexclusivefalse-mean
    • 活着:https://archive.ph/zldgz
    • “Camunda”是另一个“Activiti”分叉。因此两者的技术细节不会完全相同。然而,在Camunda手册中,有一个关于交易和“乐观锁定”概念的很好的一般性讨论:
    • https://docs.camunda.org/manual/latest/user-guide/process-engine/transactions-in-processes/#optimistic-locking
    • https://docs.camunda.org/manual/latest/user-guide/process-engine/the-job-executor/#exclusive-jobs