蓝凌EKP18产品:整体架构
一、四层架构总览EKP 流程引擎采用经典的四层分层架构从外到内依次是┌─────────────────────────────────────────────────────────┐ │ 应用层 (Application) │ │ │ │ 业务模块调用入口发起流程、审批、驳回、转办、加签... │ │ 提供给前端/第三方系统的 REST API / Java API │ │ │ │ 对应模块: sys-lbpmweb, sys-lbpmext, sys-lbpmdocking │ ├─────────────────────────────────────────────────────────┤ │ 引擎层 (Engine) │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 上层业务服务层 │ │ │ │ 流程模板管理、模拟仿真、变更日志、事件监听... │ │ │ │ 对应模块: sys-lbpmservice │ │ │ └─────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 中层引擎调度层 │ │ │ │ 操作行为调度、执行参数管理、节点属性解析... │ │ │ │ 包路径: engine/manager, engine/operation │ │ │ └─────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 底层PVM 虚拟机 │ │ │ │ 执行路径管理、原子操作调度、事件分发、状态机 │ │ │ │ 包路径: pvm/ (执行、操作、事件、上下文) │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ 对应模块: sys-lbpm │ ├─────────────────────────────────────────────────────────┤ │ 持久层 (Persistence) │ │ │ │ 数据访问对象 (DAO)、ORM映射、数据库表结构 │ │ 对应子包: engine/persistence │ │ 核心表: 流程实例表、执行路径表、工作项表、流程定义表... │ ├─────────────────────────────────────────────────────────┤ │ 基础层 (Infrastructure) │ │ │ │ Spring 容器、事务管理、权限框架、缓存、消息队列... │ │ 对应模块: CORE, com, sys-cache, sys-right 等 │ └─────────────────────────────────────────────────────────┘关键认识这不是简单的四层堆叠而是两套正交系统的组合纵向按调用层次划分谁调谁横向按功能领域划分管什么同一层里不同模块各管一块互不干扰跨层时通过接口契约通信上层依赖下层下层绝不反向调用。二、引擎层深度拆解引擎层是整套系统的核心从下到上又可以细分为三个子层2.1 底层PVM 流程虚拟机PVM 是流程引擎的CPU职责纯粹而关键——只管怎么走不管走什么。它关心的内容关心不关心当前执行路径在哪个节点这个节点是审批还是发邮件原子操作的排队和执行顺序每个原子操作内部的业务细节事件如何发布和分发事件监听器做了什么业务处理执行路径的父子关系和状态转换这些数据怎么存到数据库PVM 的六大子包各司其职execution执行路径流程的当前位置指针树形结构6 种状态operation原子操作最小执行单元双队列调度event事件流程生命周期事件定义启动、进入节点、离开节点、结束…builder定义模型流程定义的抽象表示节点、路由、条件context上下文执行环境、参数传递、变量作用域service服务接口PVM 与引擎层的解耦契约EngineWire、EngineProvider2.2 中层引擎调度层这一层是 PVM 虚拟机和具体业务之间的中间件。它的核心任务是把 PVM 发出的指令翻译成具体的业务动作。关键模块Manager管理器Manager 层掌握流程运行的全局状态和环境ProcessServiceManager流程服务的总入口协调各个子系统ExecutionParameters包装流程执行时需要的全部参数实例ID、操作类型、临时变量…ProcessParameters流程实例级别的参数上下文贯通整个执行周期ResourceCache流程定义、节点配置的缓存避免每次执行都重新解析Operation操作行为Operation 层定义了人工操作的抽象行为模板AbstractOperationBehaviour所有操作行为的基类定义了接收信号→执行业务→决定路由的标准流程AbstractManualOperationBehaviour人工审批操作同意/驳回/转办等的通用逻辑AbstractAdditionOperationBehaviour加签操作的通用逻辑这些抽象类定义了模板方法——子类只需填充具体的业务逻辑调度流程由父类统一控制。Node节点类型Engine 内置了四种标准节点每种都有对应的 Behaviour行为类节点类型作用对应的 BehaviourStartNode流程起点生成发起人待办StartNodeBehaviourEndNode流程终点触发结束事件EndNodeBehaviourSplitNode并行分支网关分裂执行路径SplitNodeBehaviourJoinNode聚合分支网关等待分支汇合JoinNodeBehaviour2.3 上层业务服务层这一层最接近应用层处理流程引擎的业务外围功能。它不属于引擎核心但又是流程系统不可或缺的部分。核心模块sys-lbpmservice包含流程模板管理流程定义的发布、版本管理、变更日志模拟仿真在不产生真实数据的前提下预览流程走向事件监听处理审批通过后发通知、更新关联数据、触发下游流程流程图导入导出可视化流程图与流程定义 XML 的互转定时任务超时提醒、自动催办、过期处理外部系统对接钉钉、飞书、第三方 OA 的消息推送三、模块间的交互流程接下来我们用一次完整的审批流转串联起各层的协作关系3.1 从宏观到微观的三级视角第一级系统间视角用户浏览器 → 前端应用 → REST API → 流程引擎 → 数据库这是最粗粒度的视图每一步只看到调用方向。第二级模块级视角浏览器 │ POST /api/workitem/complete ▼ sys-lbpmweb (REST Controller) │ 调用 service 接口 ▼ sys-lbpmservice (业务服务) │ 组装参数, 执行操作行为 ▼ sys-lbpm (引擎核心) │ PVM 驱动执行路径流转 ▼ engine/persistence (持久层) │ 写入工作项状态、执行路径状态 ▼ 数据库第三级引擎内部视角这就是第六课追踪过的路径ProcessServiceManager 接收请求 │ ▼ 创建 ExecutionContext上下文 │ ▼ ExecutionWraper.signal() 激活执行路径 │ ▼ Signal 原子操作 → 节点 Behaviour.signal() │ ▼ TransitionEndTask 结束当前任务 │ ▼ TransitionStartTask 启动下一节点 │ ▼ ExecuteTask 执行节点行为3.2 关键转折点人工节点 vs 自动节点整个流转过程中有一个关键分叉ExecuteTask │ ├── [人工节点] │ 创建待办工作项 │ 设置状态 WAITING │ 通知相关人员 │ ← 执行暂停等待外部信号 │ └── [自动节点] 执行业务逻辑计算、发通知、调接口… 自动完成 继续向前流转 ← 不停顿直接进入下一节点这就是为什么流程引擎在架构上天然分成同步执行和异步等待两部分。自动节点在引擎内部一次性跑完人工节点则需要执行路径停下来等待外部用户的操作信号。四、六大关键抽象架构的好坏关键看抽象设计。EKP 流程引擎定义了六组核心抽象每一组都精准地解耦了一个维度的变化4.1 EngineWire —— 执行路径的持久化抽象PVM 层不操作数据库——它只管内存中的执行路径对象。所有创建执行路径查找执行路径删除执行路径的操作都通过EngineWire接口委托给引擎层。这意味着什么如果未来要把执行路径从关系数据库迁移到 Redis 或 MongoDB只需换一个EngineWire实现PVM 层一行代码不用改。4.2 ActivityBehaviour —— 节点行为的可插拔抽象每个节点类型对应一个ActivityBehaviour实现。引擎调度层只和这个接口打交道不关心具体节点类型。这意味着什么要扩展自定义节点比如外部接口调用节点只需实现ActivityBehaviour接口然后注册到系统中即可——不用修改引擎核心的任何代码。4.3 AtomicOperation —— 执行步骤的最小单元抽象启动任务执行任务结束任务移动父任务——每一种流转动作都封装为独立的原子操作。它们通过名称互相引用通过队列统一调度。这意味着什么要新增一种流转动作比如跳过当前节点只需新增一个AtomicOperation实现然后在合适的事件监听器中触发它。4.4 JoinStrategy —— 聚合策略的策略抽象并行分支汇合时任意一人通过还是全部通过不同场景需要不同的聚合策略。JoinStrategy接口将策略定义与引擎核心分离AnyoneJoinStrategy有一人通过即完成聚合AndJoinStrategy所有人通过才算完成聚合这意味着什么如果要支持超过半数即通过的投票模式只需新增一个VoteJoinStrategy实现通过配置即可切换无需修改分支聚合的核心逻辑。4.5 ProcessServiceManager —— 服务调用的门面抽象这是引擎对外的总入口。无论是 Web 层的 REST 接口还是第三方系统的远程调用最终都通过ProcessServiceManager进入引擎内部。它就像一个前台——统一接待分发给后台各个职能部门处理。4.6 ExecutionContext —— 一次执行的快照抽象每次操作都会创建一个ExecutionContext它封装了当前执行所需的一切当前执行路径在哪关联的流程定义是什么流程参数有哪些引擎的服务提供器是谁这相当于把执行现场打了个包——后续的所有原子操作、事件监听都基于这个上下文展开不需要反复查询数据库。五、架构中的设计模式EKP 流程引擎的设计中几个经典模式贯穿始终5.1 模板方法模式最典型的应用在操作行为层AbstractOperationBehaviour模板 │ ├── signal() ← 模板方法定义标准流程 │ ├── preSignal() ← 钩子子类可选覆盖 │ ├── doExecute() ← 抽象方法子类必须实现 │ └── postSignal() ← 钩子子类可选覆盖 │ └── 子类实现: AgreeOperationBehaviour, RejectOperationBehaviour...价值确保所有操作行为遵循统一的调度流程子类开发者只需关心业务逻辑不用管调度机制。5.2 策略模式JoinStrategy是典型策略模式。聚合节点的核心逻辑不依赖具体策略运行时动态注入。价值新增聚合方式不影响聚合节点的核心实现符合对扩展开放对修改关闭的原则。5.3 观察者模式事件驱动PVM 的整个流转过程基于事件驱动。节点进入、节点离开、任务激活、任务结束——每个关键时刻都发布事件监听器们各取所需地响应。价值新需求比如审批通过后自动发企业微信通知只需新增一个事件监听器核心流转逻辑不受影响。5.4 门面模式ProcessServiceManager作为引擎的统一入口屏蔽了内部复杂度。外部调用者不需要知道 PVM、原子操作、执行路径这些概念只需调用startProcess()、completeWorkitem()等语义明确的方法。价值降低使用门槛同时保护内部实现细节后续重构不影响外部调用方。六、架构的核心原则回顾整个架构设计可以提炼出五条原则它们共同构成了这套系统的设计哲学原则一关注点分离引擎核心只管流转不管业务。PVM 不知道什么叫审批通过它只知道当前节点结束了沿着路由走到下一个节点。审批逻辑是挂在节点上的 Behaviour 去执行的。原则二依赖倒置上层依赖接口下层实现接口。引擎层定义ActivityBehaviour接口业务层提供实现。不是引擎调用业务而是引擎调用接口接口背后是什么它不关心。原则三小步快走复杂流转 多个原子操作的链式组合。一次审批通过并流转到下一节点看似一步操作实际分解为结束当前任务 → 找到下一路由 → 启动下一节点 → 执行节点行为。每步都是独立、可跟踪、可回滚的小操作。原则四显式状态所有状态必须显式表达不允许隐含状态。执行路径的六种状态ACTIVE/WAITING/SUSPENDED/ENDING/ENDED/CONCURRENT互斥且完备。不存在既是等待又是激活的模糊情况。这种严格的状态机设计是流程可靠性的基石。原则五可观测性每个关键动作都留下痕迹。事件机制不仅是扩展机制也是观测手段。流程启动、节点进入、任务创建、操作完成——都有对应的事件。监控系统可以监听这些事件来构建执行轨迹、性能仪表盘和异常告警。