camunda job调度 - modric2jeff/archive GitHub Wiki
好的 👍 我给你整理一份 Camunda Job 生成与调度机制 的说明,并配上图例(时序/架构图),帮助你清晰理解 Job 的生成时机 和 调度时机。
🔹 Camunda Job 的生成与调度流程
1. Job 生成时机
Camunda 在以下场景会生成 Job 记录(存储到 ACT_RU_JOB 表):
-
BPMN asyncBefore / asyncAfter
- 执行到带
asyncBefore=true的活动 → 生成 Job,当前事务提交后才可执行。
- 执行到带
-
Timer events(Timer Start / Boundary / Intermediate / Cycle)
- 部署流程时或运行时 → 生成 Job,等待到期触发。
-
Failed job 重试
- Job 执行失败,根据重试策略生成新的 Job。
-
External Task
- 创建 ExternalTask 时,也会在
ACT_RU_EXT_TASK,它和 Job 表类似。
- 创建 ExternalTask 时,也会在
👉 生成特点:
- 生成 Job 的动作是在 CommandContext 内部完成的。
- Job 会被写入数据库,但必须等到 事务提交,才能被 JobExecutor 线程“看见”。
2. Job 调度时机
调度由 JobExecutor 控制,JobExecutor 是一个后台线程池,流程是:
-
Job 查询
- 周期性扫描
ACT_RU_JOB表,查询duetime <= now and suspended = false的 Job。
- 周期性扫描
-
Job 获取
- 使用
acquireJobsCmd上锁,设置lockOwner和lockExpirationTime,防止并发抢。
- 使用
-
Job 执行
- 提交到线程池,调用对应的
JobHandler。 - 如果成功,删除 Job;如果失败,生成重试 Job 或 Incident。
- 提交到线程池,调用对应的
👉 注意:
- 事务提交前生成的 Job → JobExecutor 还看不见。
- 事务提交后 → JobExecutor 可能立即扫描到并调度。
- 如果此时你在
AFTER_COMMIT去 suspend instance,可能会和 JobExecutor 抢时间。
🔹 图解说明
图 1:Job 生成与事务提交
+--------------------+ +-------------------+
| 用户触发流程执行 | | CommandContext |
| (进入某个节点) | | |
+--------------------+ +-------------------+
| |
| asyncBefore=true |
v |
生成 Job (内存中) -----------------------> | insert into ACT_RU_JOB
| |
| (还未提交) |
v |
提交事务 ---------------------------> 数据库持久化
👉 要点:Job 真正可见是在 事务提交之后。
图 2:JobExecutor 调度流程
+--------------------+
| JobExecutor |
| (后台线程池) |
+--------------------+
|
周期扫描 ACT_RU_JOB
|
v
找到 duetime <= now
且 suspended = false
|
Acquire (加锁)
|
v
提交线程池执行
|
v
JobHandler 处理逻辑
|
成功 -> 删除Job
失败 -> 重试/Incident
图 3:Race Condition(挂起 vs Job调度)
时间轴 →
-------------------------------------------------------------
1. 事务提交 -> Job 写入数据库
2. JobExecutor 正在扫描数据库
3. AFTER_COMMIT 挂起流程实例
4. JobExecutor 抢先锁到 Job
5. 执行时发现流程已挂起 -> 抛出 SuspendedException
👉 这就是为什么 deleteJob/suspendInstance 无法保证阻止 Job 执行一次。 因为 JobExecutor 抢走的瞬间,数据库里还没标记 suspended。
🔹 总结
-
生成时机:
- Job 在 流程引擎执行命令中生成,直到 事务提交后 才能被调度。
-
调度时机:
- JobExecutor 周期性查询数据库,按 dueTime 获取 Job 并执行。
-
Race condition:
- suspend/delete 和 JobExecutor 获取之间存在竞态。
- 所以 Job 可能执行一次后才被中止。
要不要我帮你画一个 更清晰的时序图(事务提交 + JobExecutor调度),用 PlantUML 或 Mermaid 代码形式,你可以直接放在文档里生成图?