Camunda并行任务的处理

2023-10-27

在工作流的编排中,有些时候会同时运行多个任务或子进程,默认的方式是串行运行,但是为了提高性能,我们会希望能并行运行。我也进行了一些测试,发现这个并行运行还不是这么简单的。

举个例子,我们现在定义一个流程,这个流程很简单,就是调用一个Http接口。然后再定义另外一个流程,在这个流程里面引用刚才定义的子流程,然后运行这个子流程多次。我们希望实现的效果是这个子流程的运行能够并行。

首先我们先简单定义一个Http接口,在这个接口接收到Reqest之后,简单的休眠10秒之后再返回。这个接口很简单,代码就不附上了。

然后我们定义一个简单的流程,里面包含一个Service Task,是调用这个Http接口的。这个流程的BPMN内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
  <bpmn2:process id="Process_12345" name="Test_12345" isExecutable="true">
    <bpmn2:startEvent id="StartEvent_1">
      <bpmn2:outgoing>Flow_1lqf9ii</bpmn2:outgoing>
    </bpmn2:startEvent>
    <bpmn2:sequenceFlow id="Flow_1lqf9ii" sourceRef="StartEvent_1" targetRef="Activity_1jsutqa" />
    <bpmn2:endEvent id="Event_03vs1kv" camunda:asyncBefore="true">
      <bpmn2:incoming>Flow_179keqc</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="Flow_179keqc" sourceRef="Activity_1jsutqa" targetRef="Event_03vs1kv" />
    <bpmn2:serviceTask id="Activity_1jsutqa" name="调用HTTP接口" camunda:resultVariable="newNEType">
      <bpmn2:extensionElements>
        <camunda:connector>
          <camunda:inputOutput>
            <camunda:inputParameter name="url">http://127.0.0.1:7777/getDeviceList</camunda:inputParameter>
            <camunda:inputParameter name="method">POST</camunda:inputParameter>
            <camunda:inputParameter name="headers">
              <camunda:map>
                <camunda:entry key="Accept">application/json</camunda:entry>
                <camunda:entry key="Content-Type">application/json</camunda:entry>
              </camunda:map>
            </camunda:inputParameter>
            <camunda:inputParameter name="payload">{"neType": "${execution.getVariable("neType")}",
"test": "${execution.getVariable("test")}"}</camunda:inputParameter>
          </camunda:inputOutput>
          <camunda:connectorId>http-connector</camunda:connectorId>
        </camunda:connector>
      </bpmn2:extensionElements>
      <bpmn2:incoming>Flow_1lqf9ii</bpmn2:incoming>
      <bpmn2:outgoing>Flow_179keqc</bpmn2:outgoing>
    </bpmn2:serviceTask>
  </bpmn2:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_12345">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="192" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_03vs1kv_di" bpmnElement="Event_03vs1kv">
        <dc:Bounds x="432" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1fzq8lj_di" bpmnElement="Activity_1jsutqa">
        <dc:Bounds x="280" y="80" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_1lqf9ii_di" bpmnElement="Flow_1lqf9ii">
        <di:waypoint x="228" y="120" />
        <di:waypoint x="280" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_179keqc_di" bpmnElement="Flow_179keqc">
        <di:waypoint x="380" y="120" />
        <di:waypoint x="432" y="120" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn2:definitions>

然后我们再定义另外一个流程,这个流程里面包含一个Call Activity,这个Call Activity引用了刚才我们定义的流程。为了能让这个Call Activity能运行多次,我们需要定义一个inputCollection的变量,例如我在工作流里面定义一个Script Task,然后通过JavaScript来创建一个InputCollection:

var ArrayList = Java.type("java.util.ArrayList")
var neTypes = new ArrayList();
neTypes.add('AMF');
neTypes.add('SMF');
neTypes.add('UPF');
neTypes.add('ENUM');
neTypes.add('SPG');
neTypes.add('PCC');
neTypes;

然后创建一个Call Activity,在配置里面选择类型是并行运行多实例,即三条竖线的小图标,然后在Multi-Instance属性里面的Collection,设置为${neTypes},即刚才Script Task输出的变量。在Element Variable里面输入neType,这样当工作流运行时,就会遍历Collection里面的元素,把其赋值为neType,然后传给Call Activity执行。另外,在Multi-Instance里面的Asynchronous before选项也要勾上,但是Exclusive选项不要勾选。这样当流程执行到Call Activity之前,会暂停,然后创建线程任务来异步运行Call Activity。如果不这样设置,那么即使我们设置Call Activity是并行运行,但是仍然是串行执行。如下图所示:

 以下是这个流程定义的BPMN代码:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
  <bpmn2:process id="Process_12345" name="Test_12345" isExecutable="true">
    <bpmn2:startEvent id="StartEvent_1">
      <bpmn2:outgoing>Flow_1lqf9ii</bpmn2:outgoing>
    </bpmn2:startEvent>
    <bpmn2:sequenceFlow id="Flow_1lqf9ii" sourceRef="StartEvent_1" targetRef="Activity_1jsutqa" />
    <bpmn2:endEvent id="Event_03vs1kv" camunda:asyncBefore="true">
      <bpmn2:incoming>Flow_179keqc</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="Flow_179keqc" sourceRef="Activity_1jsutqa" targetRef="Event_03vs1kv" />
    <bpmn2:serviceTask id="Activity_1jsutqa" name="调用HTTP接口" camunda:resultVariable="newNEType">
      <bpmn2:extensionElements>
        <camunda:connector>
          <camunda:inputOutput>
            <camunda:inputParameter name="url">http://127.0.0.1:7777/getDeviceList</camunda:inputParameter>
            <camunda:inputParameter name="method">POST</camunda:inputParameter>
            <camunda:inputParameter name="headers">
              <camunda:map>
                <camunda:entry key="Accept">application/json</camunda:entry>
                <camunda:entry key="Content-Type">application/json</camunda:entry>
              </camunda:map>
            </camunda:inputParameter>
            <camunda:inputParameter name="payload">{"neType": "${execution.getVariable("neType")}",
"test": "${execution.getVariable("test")}"}</camunda:inputParameter>
          </camunda:inputOutput>
          <camunda:connectorId>http-connector</camunda:connectorId>
        </camunda:connector>
      </bpmn2:extensionElements>
      <bpmn2:incoming>Flow_1lqf9ii</bpmn2:incoming>
      <bpmn2:outgoing>Flow_179keqc</bpmn2:outgoing>
    </bpmn2:serviceTask>
  </bpmn2:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_12345">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="192" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_03vs1kv_di" bpmnElement="Event_03vs1kv">
        <dc:Bounds x="432" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1fzq8lj_di" bpmnElement="Activity_1jsutqa">
        <dc:Bounds x="280" y="80" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_1lqf9ii_di" bpmnElement="Flow_1lqf9ii">
        <di:waypoint x="228" y="120" />
        <di:waypoint x="280" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_179keqc_di" bpmnElement="Flow_179keqc">
        <di:waypoint x="380" y="120" />
        <di:waypoint x="432" y="120" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn2:definitions>

还有一点需要注意的,那就是在Call Activity引用的流程里面,在end event那里也需要设置Asynchronous before和Exclusive,不然的话Call Activity运行的次数会和我们预计的不同,会更多一些。按照网上的解释,由于可能存在多个线程同时运行这个子进程,但是Camunda只允许同一个进程中只有一个线程是激活的,因此只有1个线程是成功运行,其他的线程将重试运行,因此我们就会观察到有多于我们预计的运行次数。在End envent设置Async before可以阻止线程重复运行。

运行流程,从HTTP接口打印的调用日志,可以看到子流程确实是并行运行的。

在实际项目中,我还发现了一个奇怪的问题,就是我在Call Activity并行运行多个子进程,但是其中一个子进程会一直运行而不结束,其他子进程则没有这个问题。当时想了好久也没找到有啥问题,后来观察了一下这个子进程,其运行时间较长,因为要处理的数据比其他子进程要多,大概运行一次要5分多钟的时间。我又查看了一下官网上的配置描述,发现其中在任务执行里面有一个配置参数是lock-time-in-millis,默认配置刚好是5分钟,因此很有可能是因为超过5分钟这个任务还没结束,因此Camunda又启动了另外一个任务来重复执行,因此造成的现象就是好像这个任务一直在运行。找到问题之后,我把这个配置改为15分钟,即解决问题。当然按照官网的解释,另一种更好的解决办法是,当有任务需要运行长时间时,最好是改为external task的方式交由外部执行,当外部执行完毕之后发送消息给任务即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Camunda并行任务的处理 的相关文章

  • 在 Eclipse 中跨文件搜索注释掉的代码

    有没有一种快速方法可以在 Eclipse 中查找 Java 文件中所有注释掉的代码 也许是搜索中的任何选项 或者任何可以执行此操作的附加组件 它应该只能找到被注释掉的代码 而不是普通的注释 在 Eclipse 中 我只是在打开正则表达式复选
  • 如何在 Java 中根据 XSD 1.1 验证 XML?

    在 Java 中根据 XML Schema 1 1 验证 XML 文件的最佳方法是什么 我从中获取了代码tutorial http www ibm com developerworks xml library x javaxmlvalida
  • Android - 内容值覆盖现有行

    我正在尝试使用插入值ContentValues 我已将 5 个值插入到 5 列中 运行应用程序后 我只有最后一组值的行ContentValues 前四组未插入 ContentValues cv new ContentValues cv pu
  • 使用 spring security 找不到 AuthenticationProvider

    我一直在尝试使用 x509 证书通过 LDAP 对用户进行身份验证 但似乎无法正常工作 我声明了一个身份验证提供程序 但仍然抛出错误 提示没有提供程序 这是我的调试输出 INFO Initiating Jersey application
  • java中main的返回类型

    我想知道为什么java中main方法只有void返回类型 public static void main String args 为什么main方法除了void之外没有其他返回类型 Thanks 简短的回答是 因为这就是语言规范 http
  • Java中通过FTP创建文件夹层次结构

    Java 是否有现成的功能可以在远程 FTP 服务器上创建文件夹层次结构 Apache Commons 确实提供了 FTP 客户端 但我找不到创建目录层次结构的方法 它确实允许创建单个目录 makeDirectory 但创建整个路径似乎并不
  • 在 IntelliJ 中创建可执行 JAR(Java 18、JavaFX 18 Maven 项目),“警告:不支持的 JavaFX 配置...”

    我有一个 Java 18 JavaFX 18 Maven 项目 除了 javaFX 库之外 它还有很多库需要包含在工件中 我想创建一个工件 一个 jar 其中包含所有依赖项 我开始按照这个视频来创建 jar https www youtub
  • 将 @RequestLine 与 Feign 一起使用

    我有一个工作 Feign 接口定义为 FeignClient content link service public interface ContentLinkServiceClient RequestMapping method Requ
  • 检测 JSON 数组中没有重复项的最快正确方法是什么?

    我需要检查数组中的所有项目是否都是唯一的serde json Value 由于该类型没有实现Hash我想出了以下解决方案 use serde json json Value use std collections HashSet fn is
  • 一个领域模型,多个 json 视图

    我们有一组域类 它们使用球衣服务通过 jackson 序列化为 json 我们目前正在使用 JAXB 对类进行注释 尽管我们并不局限于此 这很好用 但我们希望为不同的用例提供不同的类序列化 Web site 移动应用程序 管理工具 公共AP
  • 在 HttpClient4 中使用 PoolingHttpClientConnectionManager 的正确方法出现问题 java.lang.IllegalStateException: 连接池关闭

    我正在 Java 中利用 HTTPclient4 发送 HTTP 请求并处理 HTTP 响应 我想使用连接池来提高性能 但我无法找到合适的方法来做到这一点 我正在 Java 中利用 HTTPclient4 发送 HTTP 请求并处理 HTT
  • Polymer core-ajax 不会发布 JSON?

    我正在使用 core ajax 来检索 JSON 数据 将组件翻转为 JSON 格式回传到服务器则完全是另一回事 在所有情况下 无论传入的 contentType 或 handleAs 参数如何 作为输入传入的 JSON 对象似乎都会被转换
  • JTable中动态加载大量数据

    这是我的问题 我目前有一个 JTable 其中包含 5 000 到超过 200 000 行 你知道我要说什么了 数据已经加载到内存中了 这不是问题 但是如何 我可以创建一个高效的 JTable 以便它只加载以下行 是可见的 并且任何事件仅作
  • 从 AJP 连接器请求中检索 Shibboleth 属性

    当我在 Apache 上运行 Shibboleth 身份验证时遇到了一个奇怪的问题 当 Tomcat7 在后端运行时 Apache 通过 mod proxy ajp 发送所有内容 Shibboleth 的参数也是如此 In the 文档 h
  • Admob - 没有广告可显示

    你好 我尝试制作一些在 Android 手机上显示广告的示例程序 并尝试在 v2 2 的模拟器上测试它 代码中的一切似乎都很好 但调试器中的 AdListener 表示 响应消息为零或空 onFailedToReceiveAd 没有广告可显
  • 如何手动添加Android Studio依赖

    我多次尝试向我的项目添加依赖项 但每次都会出现错误 我想添加它们的依赖项是 de hdodenhof circleimageview 1 3 0 and com github bumptech glide glide 3 6 1 所以我想下
  • 如何使用 AEM 解析 org.apache.http.ssl?

    最终 我尝试在 Java 代码中使用 AWS S3 库来通过 AEM 启用服务器端 S3 上传 但在安装依赖项和 或由 AEM 识别时遇到了问题 每次我添加新的依赖项时 都会弹出五个问题 在我尝试构建的这个包中 这是我看到的错误 The i
  • 在测试期间调用预定方法[重复]

    这个问题在这里已经有答案了 我正在使用 Maven 开发 SpringBoot 应用程序 我有一个班级 Component有方法的注释m与 Scheduled initialDelay 1000 fixedDelay 5000 注解 这里f
  • 在 Vavr 中结合任一者?

    我有几个Vavr https www vavr io Either https www vavr io vavr docs either的 我想调用一个函数Right每个 Either 的值 例如 Either
  • Java applet 是否会违反同源策略

    我需要请求一些东西并从其他域获取信息 我知道由于同源政策 javascript 无法做到这一点 我的另一个选择是通过我的服务器发出代理请求 我不希望请求来自我的服务器的 IP 也不想为我的服务器创建额外的负载 并且希望客户端这样做 是否可以

随机推荐

  • 图灵奖得主Judea Pearl:人工智能是如何走出死胡同的?

    作者 Judea Pearl Danna Mackenzie 编辑 Natalie AI 前线导读 人工智能研究专家 Judea Pearl 及其同事领导的因果关系革命突破多年的迷雾 厘清了知识的本质 确立了因果关系研究在科学探索中的核心地
  • 不同视角下的存储协议栈

    复杂度3 5 机密度3 5 最后更新2021 05 03 我们把AIX的存储协议栈归纳一下 从两个不同视角来观察 以AIX驱动实现视角 主要是文件系统驱动程序 被称为内核扩展可能更恰当 不过具体叫什么并不重要 LVM驱动程序 磁盘设备驱动程
  • Java小白一个,可以直接学习SpringBoot来做毕设吗?

    个人建议不要跳过SSM 很多人想要跳过SSM直接上手SpringBoot 但是SpringBoot中自动化配置 条件注解 Java配置等东西都基于Spring的 Java配置是Spring3开始提供的 条件注解也是Spring中的内容 很多
  • AGV轨迹matlab仿真,两轮差速AGV的轨迹跟踪控制研究 Study on Trajectory Tracking Control of Two-Wheel Difference Speed of...

    Software Engineering and Applications Vol 06 No 04 2017 Article ID 21608 9 pages 10 12677 SEA 2017 64007 Study on Trajec
  • QT学习14:QtXlsx操作Excel表

    一 前言 操作excel方式有 QAxObject 和QtXlsx 区别 Qt自带的QAxObject库操作excel的前提是电脑已经安装微软的Office 包含EXCEL 而QtXlsx可以直接使用免装Office且操作更简单 二 QtX
  • CNZZ埋点及点击量统计方法

    1 引入cnzz统计代码 document write unescape 3Cspan id 你的cnzzID 3E 3C span 3E 3Cscript src https s9 cnzz com z stat php 3Fid 3D1
  • Irrlicht引擎Shader渲染的BUG

    修改2 丢人了 回头一看原来的理解还是不够完整 如果在视图空间计算光照等 一般都会将法线变换到视图空间 想当然的做法是用视图矩阵来变换法线 这么做只有在物体没有缩放或是一致性缩放的情况下才是正确的 若是物体有非一致性缩放 uniform s
  • Python多版本管理工具--pyenv

    我们在平时的项目开发或者学习中 有可能使用不同的Python版本 大家都知道Python的版本非常多 如果我们把需要的不同版本的Python都下载到服务器上 管理起来会非常困难 多版本并存又容易互相干扰 搞不好整个服务器的Python环境会
  • WebSocked、SSE、http1.0、http1.1和http2.0之间的关系

    1 WebSocked是个啥 首先 WebSocked是html5搞出来的一种新的协议 所以和http没有什么联系 要说非要有联系就是他借用了http协议来完成一部分的握手 但它和http一样都是一种连接协议 建立在tcp协议之上 使用在应
  • 服务器端Windows系统下SVN配置

    服务器端Windows系统下SVN配置 在局域网或者公网上进行SVN配置 即客户端与服务器端不是同一台电脑 则服务器端需要利用相关软件进行相应配置 客户端配置请参见 Windows系统下SVN 本地配置 所需软件 Visual SVN Se
  • 实证研究的步骤_写一篇论文的大致步骤是什么呢?

    大部分写过论文的人都知道 完成一篇大论文 准备时间少则数月多则数年 一旦准备完成 论文不过数天或数周就可以完成 下面我们简单总结一下写一篇论文的大致步骤有哪些 一 选题 选题是否恰当 对于论文写作有非常大的影响 论文选题可以从本专业未研究过
  • 【仙女踩坑实录】VirtualBox设置中需要禁用硬件虚拟化才能启动虚拟机

    最近在用virtual box做实验 在设置中提示 需要禁用硬件虚拟化才能启动虚拟机 确认按钮灰色 并且无法启动虚拟机 于是重启 进到bios系统 网上说按F2或者根据电脑上的提示再开机的时候一直按就能进入 我没进去 不过幸好 之前设置过g
  • 【编译原理】LL(1)文法分析全过程(FIRST/FLLOW/SELECT集等)实现(c++语言)

    注 本程序只能进行LL 1 文法的分析 非LL 1 文法请转化为LL 1 文法 变量声明 string M 2000 2000 任务分析表 stack
  • JMX+Prometheus监控Grafana展示

    文章目录 概述 Java代码使用PrometheusApi统计监控指标 Prometheus Grafana展示 概述 最近在阅读InLong的源码 发现它采用通过JMX Prometheus进行指标监控 这里做了下延伸将介绍使用JMX P
  • 【配电网重构】高比例清洁能源接入下计及需求响应的配电网重构【IEEE33节点】(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 2 1 数据 2 2 DG 与负荷 24 h 功率分布曲线 2 3 需求响应措施对重构结果的
  • 无需Avatarify 无需剪辑工具 一键生成多人版 “蚂蚁呀嘿“视频

    2021年3月1日更新2 1 调整人脸区域为椭圆 比圆形更贴合脸型 占用的面积变小 2 修复了人脸出现黑边的问题 如果人脸区域不合适 可调整ratio参数 2021年3月1日更新 1 调整人脸区域为圆形 更贴合脸型 占用的面积变小 2 增加
  • .net C#反编译及脱壳常用工具--小结

    1 Reflector 微软自家工具 推荐 Reflector是最为流行的 Net反编译工具 Reflector是由微软员工Lutz Roeder编写的免费程序 Reflector的出现使 NET程序员眼前豁然开朗 因为这个免费工具可以将
  • gin 十. gin-contrib之secure 支持https与安全设置

    目录 一 实现https 二 防止XSS CSRF 一 实现https gin默认是http接口 前面也了解到gin中存在一个子包 gin contrib secure 内部提供了一些安全相关的中间件 例如HTTPS重定向 内容安全策略 C
  • VS2017社区版30天到期无法使用的激活方法

    VS2017社区版30天到期无法使用的激活方法 VS2017社区版是免费的 但是第一次安装时 没有登录 导致只要30天的试用期 现在试用期结束 无法使用 本教程就是解决这个问题 我先在控制面板中将2017社区版软件卸载了 其实 事实证明完全
  • Camunda并行任务的处理

    在工作流的编排中 有些时候会同时运行多个任务或子进程 默认的方式是串行运行 但是为了提高性能 我们会希望能并行运行 我也进行了一些测试 发现这个并行运行还不是这么简单的 举个例子 我们现在定义一个流程 这个流程很简单 就是调用一个Http接