ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Flowable CMMN 引擎架构深度解析:从共享服务、Command 拦截器到 Plan Item 状态机的运行原理

Flowable CMMN 引擎架构深度解析:从共享服务、Command 拦截器到 Plan Item 状态机的运行原理 Flowable CMMN 引擎架构深度解析从共享服务、Command 拦截器到 Plan Item 状态机的运行原理【免费下载链接】flowable-engineA compact and highly efficient workflow and Business Process Management (BPM) platform for developers, system admins and business users.项目地址: https://gitcode.com/GitHub_Trending/fl/flowable-engine本篇技术指南以 Flowable 官方文档 CMMN 引擎架构章节 为骨架系统讲解 Flowable CMMN 引擎的内部运行机制它如何与 BPMN 引擎共享 task、variable、identity、job 等底层服务API 调用如何经 Command/CommandExecutor/CommandInterceptor 流水线进入 Agenda 执行以及以数据驱动的EvaluateCriteriaOperation与 Plan Item 严格状态机为何是 CMMN 与 BPMN 最本质的差异。读完你将掌握 CMMN 引擎的完整调用链并学会通过 Debug 日志观察案例实例Case Instance的每一步演化。CMMN 引擎在 Flowable 引擎生态中的位置Flowable 是一个多引擎生态BPMN 流程引擎、CMMN 案例引擎、DMN 决策引擎、App 引擎与 Event Registry 各自负责不同领域但并非各自为政。CMMN 引擎在设计上与其他引擎保持一致的风格其上层构建于两类服务之上CMMN 专属服务负责案例模型的部署、案例实例的创建、计划项Plan Item的生命周期推进等 CMMN 语义共享服务shared servicestask、variable、identity、job 四个服务独立于任何具体引擎存在被多个引擎复用底层 Entity / DataManager 层负责低层持久化与其他引擎的实现方式对等例如通过 MyBatis 映射到 ACT_CMMN_* 等数据表。这一分层带来的直接收益是跨引擎的数据统一。以任务为例BPMN 引擎产生的 User Task 与 CMMN 引擎产生的 Human Task 会落到同一套任务服务中可以通过同一套 API 查询与管理异步执行器同理BPMN 的定时器/异步任务与 CMMN 的定时事件监听器Timer Event Listener共用同一套异步逻辑甚至可以由同一个中央执行器统一调度。第二个收益是资源共享与事务统一。当多个引擎被同时启用这在真实项目中是常态它们会尽可能共享资源一次数据库事务可以横跨多个引擎的操作查询缓存lookup caches共用持久化本身独立于引擎实现。这意味着在一个事务中同时推进流程实例与案例实例不会引入额外的分布式一致性问题。一次 CMMN API 调用的完整旅程官方文档给出了一张高层的 API 调用流图展示了从引擎入口到持久化的完整链路从高层视角看一次典型的 CMMN 操作遵循如下五个阶段创建引擎一个CmmnEngine实例由CmmnEngineConfiguration创建配置既可以来自配置文件也可以完全通过代码编程式构建服务门面CmmnEngine以服务形式对外暴露 Flowable CMMN API包括CmmnRepositoryService、CmmnRuntimeService、CmmnTaskService、CmmnHistoryService、CmmnManagementService服务命名与职责划分与其他引擎保持一致命令化每一个 API 方法都被转换为一个Command实例交给CommandExecutor执行CommandExecutor内部会使其穿过一叠CommandInterceptor拦截器这些拦截器承担事务管理等多种横切职责编排计划最终该Command通常会除非是纯数据修改型命令在CmmnEngineAgenda上规划一个CmmnOperation执行直到空操作会不断从 Agenda 中取出执行直到没有剩余操作典型地一个操作在自身逻辑执行中会规划出新的操作从而形成级联。上述链路在源码中有清晰的落点。CmmnEngine接口定义于 CmmnEngine.java它暴露getCmmnRuntimeService()、getCmmnTaskService()、getCmmnManagementService()、getCmmnRepositoryService()、getCmmnHistoryService()以及getCmmnEngineConfiguration()此外还提供startExecutors()用于启动异步执行器异步 job 与异步历史前提是它们在配置中被设置为自动激活。从配置到引擎实例配置文件与编程式两种构建方式CmmnEngineConfiguration是引擎的构建蓝图文档明确指出它可来自配置文件或编程式创建。从源码结构看配置类集中承载了引擎的全部可调参数例如异步执行器配置asyncExecutorActivate决定引擎创建后是否立即启动异步执行器相关参数控制 job 轮询间隔、线程池大小等数据库配置databaseType、dataSource、databaseSchemaUpdate如true、create-drop、drop-create等决定引擎如何初始化与维护数据表历史配置historyLevel控制历史数据的记录粒度Agenda 相关配置agendaFutureMaxWaitTimeoutProvider等用于控制操作执行超时见 DefaultCmmnEngineAgenda.java 中对超时提供者的引用。编程式创建的最简形态与 Flowable 其他引擎一致CmmnEngineConfiguration cmmnEngineConfiguration new CmmnEngineConfiguration() .setJdbcUrl(jdbc:h2:mem:flowable;DB_CLOSE_DELAY1000) .setDatabaseSchemaUpdate(CmmnEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); CmmnEngine cmmnEngine cmmnEngineConfiguration.buildCmmnEngine();配置文件方式则是在 Spring 容器或应用装配阶段通过 XML/属性文件注入配置对象再由容器负责buildCmmnEngine()。无论哪种方式最终得到的都是同一个CmmnEngine实例后续所有 API 调用都从它派生。共享服务架构跨引擎的任务、变量、身份与 Job 统一文档特别强调task、variable、identity、job 这四个共享服务独立于引擎CMMN 引擎只是它们的消费者之一。这一设计的两个直接收益统一数据视图BPMN 引擎与 CMMN 引擎产生的任务会汇入同一任务存储可通过同一 API 查询、认领、完成定时器与异步 job 也走同一套逻辑可由一个中央执行器统一管理资源共享与事务贯穿多引擎并存时数据库事务可以横跨多次引擎调用查询缓存共用持久化层独立于引擎自身。从模块划分上也能印证这一点仓库中 task、variable、identity、job 各自拥有独立的 service 模块如modules/flowable-task-service、modules/flowable-variable-service、modules/flowable-idm-engine、modules/flowable-job-service而 CMMN 引擎位于modules/flowable-cmmn-engine它们通过flowable-cmmn-engine-configurator等装配模块组合在一起。CMMN 专属服务如CmmnRuntimeService则位于modules/flowable-cmmn-api。Agenda 与 OperationCMMN 引擎的核心执行模型Agenda议程是 CMMN 引擎运转的中枢。文档给出的抽象描述是操作不断从 Agenda 取出执行执行过程中又规划出新的操作。源码中的实现类是 DefaultCmmnEngineAgenda.java它继承自 Flowable 公共的AbstractAgenda并针对 CMMN 做了两项关键强化其一操作去重与代价优化。源码注释明确写道EvaluateCriteriaOperation评估条件操作是最昂贵的操作因此它被规划时总是被追加到操作列表的末尾而其他操作总是排在其之前——因为其他操作可能触发新的评估需求。DefaultCmmnEngineAgenda内部维护了独立的LinkedListEvaluateCriteriaOperation evaluateCriteriaOperations普通操作进普通队列评估操作进专用队列getNextOperation()在普通队列为空时才取出评估操作执行。这正是文档所述引擎在检测到重复或无用的评估时会做优化的实现基础。其二操作类型即状态迁移。Agenda 上提供的planXxxOperation方法族直接对应 CMMN 语义中的各类状态迁移案例级planInitPlanModelOperation、planCompleteCaseInstanceOperation、planManualTerminateCaseInstanceOperation、planTerminateCaseInstanceOperation、planReactivateCaseInstanceOperation计划项级planCreatePlanItemInstanceOperation、planActivatePlanItemInstanceOperation、planStartPlanItemInstanceOperation、planEnablePlanItemInstanceOperation、planDisablePlanItemInstanceOperation、planCompletePlanItemInstanceOperation、planOccurPlanItemInstanceOperation、planExitPlanItemInstanceOperation、planSuspendPlanItemInstanceOperation、planTerminatePlanItemInstanceOperation、planFailPlanItemInstanceOperation、planResumePlanItemInstanceOperation、planTriggerPlanItemInstanceOperation等评估与监听planEvaluateCriteriaOperation、planEvaluateVariableEventListenersOperation。每个plan方法内部都通过addOperation(...)创建一个对应的操作对象入队。操作实现类集中在modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/agenda/operation/目录下共 40 余个包括InitPlanModelInstanceOperation、ActivatePlanItemInstanceOperation、StartPlanItemInstanceOperation、CompletePlanItemInstanceOperation、OccurPlanItemInstanceOperation、TerminatePlanItemInstanceOperation、CompleteCaseInstanceOperation、EvaluateCriteriaOperation、EvaluateVariableEventListenersOperation等。这些操作共同实现了 CMMN 规范的完整状态机。BPMN 是本地推进CMMN 是数据驱动文档指出BPMN 引擎与 CMMN 引擎有一个概念性的重大差异BPMN 引擎本质上是本地local的引擎观察当前状态检查流程前方是什么然后继续推进——当然这是简化描述存在大量例外操作但用于概念区分是准确的CMMN 引擎则不同在 CMMN 中数据扮演核心角色一处数据的变化可能在案例定义Case Definition的多个位置触发一连串反应。因此每当发生变更时引擎都会规划并执行EvaluateCriteriaOperation并且会在检测到重复或无效评估时进行优化。EvaluateCriteriaOperation的源码位于 EvaluateCriteriaOperation.java其run()方法展示了完整的评估逻辑若案例实例已被删除直接标记为 noop 返回先评估退出哨兵exit sentry若满足则规划TerminateCaseInstanceOperation终止整个案例实例并传递退出类型与退出事件类型否则评估计划项条件plan item criteria若配置要求评估阶段与案例完成evaluateStagesAndCaseInstanceCompletion为 true且计划模型已满足完成条件、没有条件变更或活跃子项、且案例实例不处于终态则记录 Debug 日志并规划CompleteCaseInstanceOperation完成案例实例否则标记为 noop。toString()方法生成了日志中[Evaluate Criteria] case instance ... with transition xxx having fired for plan item ...的可读描述与官方文档给出的日志输出完全对应。Plan Item InstanceCMMN 的严格状态生命周期CMMN 引擎运转的核心概念是Plan Item Instance计划项实例——它表示哪些计划项Plan Item当前在案例中存活live以及它们处于什么状态。与 BPMN 大不相同的是CMMN 为计划项定义了严格的状态生命周期。这一状态机体现在三处CmmnRuntimeService的方法如startPlanItemInstance、completePlanItemInstance、triggerPlanItemInstance、terminatePlanItemInstance等每个方法对应一次受控的状态迁移查询 API可以按状态过滤计划项实例PlanItemInstance对象上的数据字段实例的当前状态字段贯穿持久化与查询。状态常量定义于 PlanItemInstanceState.java共 10 种状态状态常量值语义UNAVAILABLEunavailable计划项尚未可用默认初始态AVAILABLEavailable已具备可被激活的前提ENABLEDenabled已启用等待手动激活ACTIVEactive激活中正在执行COMPLETEDcompleted已完成FAILEDfailed执行失败SUSPENDEDsuspended挂起TERMINATEDterminated已终止DISABLEDdisabled已禁用此外状态接口还包含其他内部状态值如ASYNCHRONOUS相关标记具体可查看该文件完整定义。与之对应案例实例本身也有状态机定义于 CaseInstanceState.javaactive、completed、failed、suspended、closed、terminated。EvaluateCriteriaOperation中判断案例实例是否处于终态用的正是CaseInstanceState.END_STATES集合。用 Debug 日志透视 Agenda 的每一步文档给出了一个极具实操价值的诊断手段将 agenda 包的日志级别设为 DEBUG即可观察议程、操作与计划项实例处理的完整轨迹。以 log4j 配置为例log4j.logger.org.flowable.cmmn.engine.impl.agendaDEBUG对应 SLF4J/logback 场景则为logger nameorg.flowable.cmmn.engine.impl.agenda levelDEBUG/DefaultCmmnEngineAgenda.addOperation中正是通过LOGGER.debug(Planned {}, operation)输出每条Planned ...日志而各操作类的toString()决定了日志的具体内容。开启后一次典型案例运行会输出类似以下序列案例实例 id 为bfaf0e64-eaf4-11e7-b9d0-acde48001122Planned [Init Plan Model] initializing plan model for case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 Planned [Change PlanItem state] Task A (id: planItemTaskA), new state: [available] with transition [create] Planned [Change PlanItem state] PlanItem Milestone One (id: planItemMileStoneOne), new state: [available] with transition [create] Planned [Change PlanItem state] Task B (id: planItemTaskB), new state: [available] with transition [create] Planned [Change PlanItem state] PlanItem Milestone Two (id: planItemMileStoneTwo), new state: [available] with transition [create] Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition create having fired for plan item planItemTaskA (Task A) ...这条日志链完整展示了 CMMN 的核心运行节奏Init Plan Model案例实例启动时初始化计划模型Change PlanItem state ... transition [create]每个计划项经create迁移进入available状态——注意日志中出现的[Change PlanItem state]对应AbstractChangePlanItemInstanceStateOperation及其子类操作Evaluate Criteria每次状态变更后都会规划评估操作评估操作携带哪个计划项、哪条 transition 已触发的上下文PlanItemLifeCycleEventActivate PlanItem条件满足的计划项被激活对应ActivatePlanItemInstanceOperation随后经start迁移进入active... transition [complete]/[occur]任务完成Task与里程碑达成Milestone 走occur迁移再次触发评估收尾所有计划项进入终态后日志输出No active plan items found for plan model, completing case instance这正是 EvaluateCriteriaOperation.java 中第 67 行的 Debug 语句随后Planned [Complete case instance]案例实例完成。通过这段日志你可以非常直观地验证一个事实CMMN 的推进不是按图索骥式的线性执行而是状态变更 → 触发评估 → 满足条件 → 激活下一批计划项 → 再次评估的迭代闭环数据状态、变量变化始终是驱动力。小结一条主线串起 CMMN 引擎把整章内容收拢成一条主线CmmnEngineConfiguration创建CmmnEngine→ 服务方法包装为Command→ 穿过CommandExecutor与CommandInterceptor事务等横切逻辑→ 在CmmnEngineAgenda上规划CmmnOperation→ 操作循环执行、级联规划新操作 → 底层调用共享服务与 Entity/DataManager 完成持久化 → 数据/状态变化再次触发EvaluateCriteriaOperation直至案例完成或终止。理解这一架构对实际开发有直接帮助排查 CMMN 行为异常时打开org.flowable.cmmn.engine.impl.agenda的 DEBUG 日志即可还原引擎的每一步决策设计案例模型时意识到数据驱动 严格状态机的特点就能理解为何 CMMN 适合处理人工密集、边界模糊、依赖条件触发的场景而不是像 BPMN 那样适合刚性流程编排。相关实现细节均可直接阅读仓库源码接口层见 CmmnEngine.java执行层见 DefaultCmmnEngineAgenda.java 与operation包下的全部操作类状态定义见 PlanItemInstanceState.java。【免费下载链接】flowable-engineA compact and highly efficient workflow and Business Process Management (BPM) platform for developers, system admins and business users.项目地址: https://gitcode.com/GitHub_Trending/fl/flowable-engine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表