语雀原文链接: Camunda 开源流程引擎 学习笔记(一)

一. 为什么选择 Camunda

参见: Activiti阻碍微服务发展

二. Camunda 7 & 8

Camunda 7.x 和 Camunda 8.x 不是自然的升级关系, 他们是两个产品. Camunda 8.x 起源于 Camunda cloud, 基于云原生架构, 在扩展方面有天然的优势. 需要部署在K8S之上. 官方承诺至少未来5年内, Camunda 7.x 会继续维护.
参考官方博文: Camunda Platform 7 / 8 对比

image.pngimage.png

三. 快速入门

参考:官网quick-start
这个入门非常好, 建议依次完成6个小节.

四. 纯Java示例

参考: java-process-app

五. Spring 集成

六. Spring-Boot 集成

七. 流程引擎概念

7.1 Executions

Executions代表一个执行线,类似线程。下图中流程在receive paymentship order两个activity处创建了两个Executions.
image.png
另外,嵌入式子流程,多实例等处,流程引擎也会创建多个Executions.
Executions同时是变量的作用域,每个Executions都有独立的作用域.
流程实例本身也是一个Execution,流程实例内部的Execution组成树形结构, 流程实例本身是根节点.
查询Executions:

runtimeService.createExecutionQuery()
    .processInstanceId(someId)
    .list();

7.2 活动实例(Activity Instance)

活动实例和Executions类似, 也可以组成一个树状结构, 不同点在于他们具有不同的视角. Executions可以想象成令牌的移动线, 活动实例则是令牌经过的一些点.
活动实例的概念与执行的概念相似,但采取了不同的视角。执行可以被想象成在流程中移动的 “token”,而活动实例则代表一个活动(任务、子流程…)的单个实例。因此,活动实例的概念更加倾向“面向状态(state-oriented)”。
活动实例也构成一棵树,遵循 BPMN 2.0 所提供的范围标准。处于 “同一层次的子流程”(即,同一范围的一部分,包含在同一子流程中)的活动,其活动实例会处于树的同一层次。
例如,活动实例被用来进行流程实例的修改 和查看 Cockpit中的活动实例树.
例如:

  • 并行网关后有两个并行用户任务的流程:
ProcessInstance
  receive payment
  ship order
  • 在并行网关后有两个并行的多实例用户任务的流程:
ProcessInstance
  receive payment - Multi-Instance Body
    receive payment
    receive payment
  ship order - Multi-Instance Body
    ship order

注意:多实例活动由多实例主体和内部活动组成。多实例主体包含所有内部活动,并收集内部活动的活动实例。

  • 嵌入子流程内的用户任务:
ProcessInstance
  Subprocess
    receive payment
  • 在用户任务之后,用抛出的补偿事件进行处理。
ProcessInstance
  cancel order
  cancel shipping

查找流程实例:

ActivityInstance rootActivityInstance = runtimeService.getActivityInstance(processInstance.getProcessInstanceId());

每个活动实例被分配一个唯一的ID。这个ID是确定的,如果你多次调用这个方法,相同的活动实例ID将被返回相同的活动实例。然而,可能会分配不同的执行,见下文.

流程引擎中的执行概念与活动实例概念并不完全一致,因为执行树通常与BPMN中的活动/范围概念不一致。一般来说,执行和活动实例之间是n对1的关系,也就是说,在一个给定的时间点上,一个活动实例可以与多个执行相关联。此外,不能保证启动某个活动实例的执行也能结束它。流程引擎为了对执行树压缩进行了一些内部优化,这可能导致执行被重新排序和裁剪。这可能会导致这样的情况:一个给定的执行启动了一个活动实例,但另一个执行却结束了它。另一种特殊情况是:如果流程实例正在执行流程定义范围下面的非范围活动(例如用户任务),它将被root活动实例和用户任务活动实例所引用。
注意:如果你需要用 BPMN 流程模型来解释流程实例的状态,通常,使用活动实例树将比执行树更容易。

7.3 jobs 和 job 的定义

Camunda流程引擎包括一个名为“Job执行器(Job Executor)”的组件。Job执行器是一个调度组件,负责执行异步的后台Job。用定时器事件的例子:每当流程引擎到达定时器事件时,它将停止执行,将当前状态持久化到数据库,并创建一个Job以在未来恢复执行。一个Job有一个到期时间,这个到期时间是使用BPMN XML中提供的定时器表达式计算的。
当一个流程被部署时,流程引擎为流程中的每个可能在运行时创建Job的活动创建一个Job定义。这允许你在流程中查询关于计时器和异步活动的信息。
使用managementService,你可以查询Job。以下是选择所有在某一日期后到期的Job。

managementService.createJobQuery()
  .duedateHigherThan(someDate)
  .list()

使用managementService,你也可以查询Job的定义。以下是选择特定流程中所有Job的定义:

managementService.createJobDefinitionQuery()
  .processDefinitionKey("orderProcess")
  .list()

禁用job
禁用Job可以防止Job被执行。暂停Job的执行可以在不同的层面上进行控制。

  • Job实例级别:单个Job可以通过managementService.suspendJob(…) API直接暂停,或者在暂停一个流程实例或Job定义时过渡性地暂停。
  • Job定义级别:某个定时器或活动的所有实例可以被暂停。

通过对Job定义的暂停Job允许你暂停某个定时器或异步延续的所有实例。直观地说,这允许你暂停流程中的某个活动,其方式是所有的流程实例都会执行到它们达到这个活动,然后就因为活动被暂停而不再继续了。
让我们假设有一个以 “orderProcess” 为关键字部署的流程,它包含一个名为 “processPayment” 的服务任务。该服务任务配置了一个异步延续,导致它被Job执行器执行。下面的例子显示了如何防止 “processPayment”服务被执行:

List<JobDefinition> jobDefinitions = managementService.createJobDefinitionQuery()
        .processDefinitionKey("orderProcess")
        .activityIdIn("processPayment")
        .list();

for (JobDefinition jobDefinition : jobDefinitions) {
  managementService.suspendJobDefinitionById(jobDefinition.getId(), true);
}

7.4 变量

变量也是流程中一个比较重要的概念.
参考: process-engine-variables
变量有作用域,参见上文的Executions. 变量是根据key读取, 子域可以读取父域的变量, 父域不可读子域变量.
image.png
image.png

7.5 流程实例修改(Process Instance Modification)

提供了无视流程常规执行流, 任意指定流程执行点的能力. 对于建模良好的模型来说, 是没用的.但是, 业务复杂, 有时候需要用反模式来适应变化.
参考: process-instance-modification

7.6 流程实例重启(Process Instance Restart)

与流程实例修改一样, 都是反模式操作. 但有其应用场景. 重启流程实例有个前提, 必须将历史记录级别设置为FULL, 这个级别会记录所有变量的变化前后值.
参考:
process-instance-restart

7.7 委托代码(Delegation Code)

这个概念非常有用, 它允许您在流程执行期间发生某些事件时执行外部 Java 代码、脚本或评估表达式。
有四种不同类型委托代码:

  • Java 代理类(JAVA Delegates) 可以附加到 BPMN 服务任务
  • 变量映射(Delegate Variable Mapping) 可以附加到 发起活动
  • 执行监听器(Execution Listeners) 可以附加到令牌流动的任何实践,例如,启动一个流程实例或进入一个活动。
  • 任务监听器(Task Listeners) 可以附加到用户任务生命周期内的任何事件,例如,用户任务的创建或完成。

参考:
delegation-code

7.8 外部任务(External Tasks)

bpmn中除了人工任务外, 还可以调用seviceTask. 服务任务有两种模式:

  • 内部调用(在同一个jvm中调用), 如委托代码, 脚本等.
  • 外部任务模式: 外部客户端(业务工人)轮询拉取任务.

image.png
外部任务模式中有三个角色:

  1. Process Engine: Creation of an external task instance
  2. External Worker: Fetch and lock external tasks
  3. External Worker & Process Engine: Complete external task instance

这种模式非常时候微服务架构. Camunda提供了External Worker的Java客户端, 集成也非常容易.
参考:
external-tasks
说实话, Camunda这种基于数据库的引擎, 使用外部任务模式以及微服务编排场景下, 并发量大的情况下是会有性能问题的.
另外, 使用外部任务模式, 事件监听也不好处理.
Camunda 8 中, 使用的Zeebe引擎就是为了解决这种问题的, Zeebe中, Clients & Job Workers是一等公民:

Zeebe 架构

image.png

Zeebe 主要由三个部分组成

  • 业务的具体执行者 Job Worker & Client,Zeebe 的接入点
  • Zeebe 核心逻辑的 Zeebe cluster
  • 日志收集通 Exporter 并写入 ES
Clients & Job Workers
  • 基本功能
  • 部署流程
  • 执行业务逻辑、启动流程实例、发布消息、激活工作、完成工作、失败的工作
  • 处理操作问题、更新流程实例变量、解决错误
  • 客户端应用程序可以完全独立于 Zeebe 进行扩展和缩减 - Zeebe broker 不执行任何业务逻辑。
  • 嵌入微服务中以连接到 Zeebe 集群
  • 客户端通过 gRPC 连接到 Zeebe 网关,使用基于 HTTP/2 的传输
  • 官方支持的 Java 和 Go 客户端。 社区客户端是用其他语言创建的,包括 C#、Ruby 和 JavaScript,gRPC 能够实现跨语言的通信

原文链接: https://xie.infoq.cn/article/4e361655b83634d2a3a0c9a61

7.9 连接器(Connectors)

7.17版本的资料有点少, 在Camunda 8中, 连接器是一等公民, 作为一个核心特性来解锁.

7.10 历史和审计日志(History and Audit Event Log)

image.png
由于流程引擎不依赖历史数据库的存在来生成历史事件流,因此可以提供不同的后端来存储历史事件流。默认后端是 DbHistoryEventHandler,它将事件流记录到历史数据库Camunda提供自定义存储机制, 因此我们可以使用类似ES之类的后端存储历史数据.
历史级别控制流程引擎通过历史事件流提供的数据量。以下设置开箱即用:NONE, ACTIVITI, AUDIT, FULL, AUTO,每个基本所记录的历史信息范围参见官方文档: https://docs.camunda.org/manual/latest/user-guide/process-engine/history/

7.11 多租户

Camunda 支持多租户, 如需使用则查阅官网文档.

八. 源码探究

8.1 下载

git clone git@github.com:camunda/camunda-bpm-platform.git
源码较大, 也可以使用csdn的镜像站下载:
git clone https://gitcode.net/mirrors/camunda/camunda-bpm-platform.git

下载完成后, 检出最新的稳定tag. 本文使用7.17

8.2 编译

cd camunda-bpm-platform/
mvn clean install -DskipTests -Pdistro

注意: 有些依赖在阿里云maven仓库以及中心参考中都下载不到, maven中配置中使用camunda官方镜像站, 参考源码/settings/maven目录:

<mirror>
  <id>camunda-nexus</id>
  <mirrorOf>*</mirrorOf>
  <name>Camunda Nexus</name>
  <url>https://artifacts.camunda.com/artifactory/public/</url>
</mirror>

8.3 运行测试

engine/目录是引擎核心模块, 可以直接运行该模块下的测试以debug:
image.png

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐