工作流引擎核心设计思路!
作者:vivo 互联网服务器团队- Cheng Wangrong
一、业务背景
营销自动化平台可以支持不同用户生命周期的活动旅程策略配置 ,根据用户触发的不同活动行为,进行差异化的营销触达方案。同时各种类型活动的具体执行过程中也有不同的业务处理流程(比如审批流程和业务流转)。业务流程复杂多样,需求变更频繁,项目开发过程中会有以下痛点:
项目交付周期长:一个完整的业务流程需要从头开始按版本迭代,开发时间长,成本高。
功能重复开发测试:业务之间会掺杂着很多共性的流程,导致大量重复性开发测试工作,效率低。
维护成本高:随着项目业务的逐步发展,业务流程逐步积累,可维护性下降,系统改动牵一发而动全身。
如何将业务逻辑从控制流中剥离出来,让产研人员更聚焦于业务的实现是需要重点解决的问题。而传统OA领域使用的是久经考验的业务流程管理解决方案 —— 工作流(Workflow)。工作流是一套工业级的解决方案,由工作流管理联盟(WfMC)制定了一系列的标准。
二、工作流介绍
2.1 工作流定义
工作流(Workflow)—— 对工作流程及其各操作步骤之间业务规则的抽象,将流程中的工作组织逻辑和规则进行建模,交由计算机进行自动处理。
工作流的本质思想是:通过预定义的工作流程模板,对现实活动进行实例化的过程。简单说就是通过预设的格式或者可视化配置好流程的模板(比如一种分享活动的运行流程模板),使用时通过该模板构造出一个流程实例对象,通过实例对象完成活动运行跟踪和回溯。
2.2 工作流参考模型
WfMC工作流管理联盟为工作流制定了参考模型,其核心就是中间的工作流引擎,工作流引擎提供流程定义工具(接口1)、给使用者提供信息查询(接口2)、调用外部应用(接口3)、整合其他工作流(接口4)和监控管理(接口5)的能力。 对于大多数工作流产品而言,重点关注的是接口1和接口2的实现。
2.3 工作流引擎关键特性
流程可视化
提供可视化的流程搭建,流程视图查看能力,以及实时观测任务运行能力。
业务可编排复用
将公共业务进行组件化,可以支持任务的自由编排,自由搭建出适合的业务的不同流程。
业务和控制分离
将流程的控制(如流转、判断、循环、重试等)的任务交由工作流负责,让使用者聚焦于核心业务逻辑。
2.4 工作流引擎的类型
对于工作流的类型没有专门的标准,按照流程任务节点特性可以分为:
顺序工作流
顺序工作流的运行方式类似一种特定的流程图,上一个流程任务完成后依次进入下一个流程任务,过程不可逆。
状态机工作流
状态机工作流侧重关注的是流程任务的状态,驱使任务状态发生变化的因素一般为外部事件,即事件驱动的方式,驱使任务节点从一个状态运行到另外一个状态,节点间可逆。
规则驱动工作流
侧重于节点的运转规则,基于业务规则进行工作流程的执行,在处理具有明确目标但“规则”或规范级别不同的各种项目时,规则驱动的工作流非常有用。
可以看到不同类型的工作流不是完全割裂的,状态机工作流中也可以结合着条件和规则进行操作节点转换的过程。在软件开发中,一般会考虑结合状态机和规则驱动的工作流。
2.5 工作流引擎和状态机的差异
在之前的文章里面,我们有对状态机和工作流引擎做过一次简单的对比,事实上,两者之间并不是一个完全对等的概念:
状态机是系统状态以及这些状态之间转移和动作等行为的数学计算模型,
而工作流是对整体工作流程及其各操作步骤之间业务逻辑和规则的抽象建模。
状态机模式是事件驱动型,大多通过外部事件触发状态的自动流转;
工作流引擎更侧重于描述预定义流程任务完成之后的自动流转,可预测性会更强。
从适用场景的复杂性上看,
直接使用状态机的方式可以清晰地描绘出所有可能的状态以及导致转换的事件,适用于解决单维度、复杂度不高的业务问题,发挥灵活轻便的特点;
工作流引擎则更适合复杂的业务流程管理,解决如大型CRM复杂度更高的流程自动化问题,聚焦于改善整体业务流程的效率。
工作流引擎是可以在状态机的结构模型基础上进行构建,事实上很多开源的工作流引擎也都是基于状态机的实现方式。
了解了工作流的基本特点和使用场景之后,我们来看一下比较流行的开源工作流引擎。
三、开源工作流引擎
四、工作流引擎自研设计
4.1 使用开源工作流引擎的问题
开源工作流最大的优势是可以借助开源的资源,开箱即用,功能全面,但是与之带来的是附带的配置和表数量比较多的维护问题。以Activiti为例,使用Activiti7.0版本至少要引入二十多张表,虽然说看似是无侵入的方式,但是系统演进和维护过程中有一定的成本。特别是业务流程实例很多的时候,开发人员需要对表逻辑有更深的把控。
由于业务的客观独特性,作为业务流程组件,一般都需要根据自身业务进行二次开发适配。 比如需要根据自身组织架构,进行流程节点用户角色权限的管控;将自身的业务能力插件化,加入工作流程配置中,进行拦截回调等。
4.2 自研引擎核心设计思路
4.2.1 引擎核心模块
回归工作流的本质, 工作流是通过预定义的流程模板,对现实活动进行实例化的过程。一个基本的工作流引擎主要包括三大核心部分:
流程模板创建
根据业务规则和逻辑,创建流程模板,设置每一个节点的操作和变更路径。基于模板创建,可以延伸出流程设计器、插件式节点,多样化的模板文件格式、模板持久化等。
流程实例发布
根据流程模板,创建一个流程实例,流程模板和流程实例的关系类似类和对象的关系。比如说工单系统管理员定义好一个审批流模板(流程模板),用户点击创建一个工单(流程实例)。基于流程实例发布,又可以延伸出实例实时观测,节点变迁记录回溯,实例状态持久化,失败重试,事务控制等。
任务流程执行
创建好流程实例之后,流程实例只需要按照流程模板的定义独立执行各自实例的任务,不同的实例之间互不影响,完成各自实例的生命周期。
4.2.2 引擎核心设计
① 应用容器启动时,加载流程引擎环境配置,包括解析器构造,流程引擎上下文,流程定义文件路径等。
② 读取定好的流程定义文件,进行流程节点解析,构建好执行上下文,将流程节点放到内存缓存中。
③ 业务侧进行流程创建,启动一个新的流程实例,同时将业务流程和流程实例进行绑定。
④ 运行流程实例各个节点,将每个流程节点进行持久化保存。
4.3 具体实践
① 引擎核心服务。
引擎操作的主要对外接口,包括启动流程实例,和获取相关流程定义模板,流程实例,流程节点的服务。
public interface FlowEngine {/*** 根据流程定义key,参数列表启动流程实例**/FlowInstance startInstance(String processDefKey, Map<String, Object> args);/*** 根据流程定义主键ID,参数列表执行流程任务(推动流程自动流转)* 统一事务控制*/void execInstance(Long instanceId, Map<String, Object> args) throws FlowAuthorityException;/*** 获取流程定义process服务**/ProcessService process();/*** 获取流程实例服务**/InstanceService instance();/*** 获取任务节点服务**/TaskService task();
}
② 流程定义服务。
主要是针对流程定义模板的创建和发布,可以根据具体的实现类来支持不同的创建方式。
public interface ProcessService { /*** 创建流程定义模板**/void create(String definition);/*** 发布流程定义模板**/void deploy(String fileName);/*** 获取流程key对应的流程定义*/FlowProcess getProcessByDefKey(String processDefKey);
}
③ 流程实例服务。
提供流程实例创建持久化和流程实例执行的入口。
public interface InstanceService {/*** 创建流程实例**/FlowInstance createInstance(FlowProcess process, Map<String, Object> args);/*** 执行流程实例** @param instanceId 流程实例id*/void exec(Long instanceId);/*** 根据id获取流程实例** @param instanceId* @return*/FlowInstance getById(Long instanceId);
}
④ 流程任务节点服务。
提供流程节点具体每个任务的创建和查询。
public interface TaskService {/*** 根据任务模型、执行对象创建新的任务**/FlowTask createTask(TaskModel taskModel, Execution execution);/*** 完成任务**/FlowTask complete(Long taskId, Map<String, Object> args);/*** 获取流程实例中正在进行的任务**/FlowTask getActiveTask(Long instanceId);/*** 获取流程实例上一个已完成的任务**/FlowHistTask getLastDoneTask(Long instanceId);
}
其中核心的方法就是
FlowEngine#startInstanceByKey,启动流程实例。基于流程定义,创建一个流程实例对象。
FlowEngine#execInstance,执行流程实例任务,通过传入的上下文参数(操作人,操作变量等),按照流程定义的节点任务,推进流程实例的自动流转。
4.4 思考和扩展
流程定义解析性能。
由于目前设计是在应用启动时对所有的流程定义文件进行加载和解析,流程定义文件过多时会影响应用启动速度,可以通过多线程解析和懒加载(使用时解析)两种方式进行优化。
流程定义版本兼容性。
由于业务流程不是一成不变的,在项目发展过程中会不断进行迭代,需要对前面不同的流程进行兼容。
流程节点插件化和编排能力。
将基础服务进行提取公用,以支持绘制不同流程的插件化和编排能力。
流程执行监控能力。
对流程任务节点执行情况进行埋点上报,系统自动进行监测告警。
五、总结
本文分析了引入工作流引擎的背景,驱使业务逻辑从控制流中剥离出来,让产研团队更聚焦于业务,解决研发效率低的问题。
工作流的本质思想是通过预定义的工作流程模板,对现实活动进行实例化的过程。一般需要具备流程可视化、业务可编排复用、 业务和控制分离的基本能力。一般常见的工作流分为顺序工作流、状态机工作流和规则驱动工作流,开源工作流框架中最常见的是状态机工作流,利用事件驱动的方式,驱使流程运转。
同时简单介绍了业界比较流行的几种开源工作流引擎的特点,结合开源工作流引擎的特点的问题,并且针对多样化和迭代频繁的业务流程, 以工作流的本质思想为出发点,我们自研了一套轻量级的工作流引擎,分享了在实践过程中的设计思路和总结思考。
强势开源一款小程序!
2021-11-07
强力推荐一个完善的物流(WMS)管理项目(附代码)
2021-10-23
推荐一个 Spring Boot + MyBatis + Vue 音乐网站
2021-10-19
分享一套家庭理财系统(附源码)
2021-09-20
推荐一个互联网企业级别的开源支付系统
2021-09-04
推荐一套开源通用后台管理系统(附源码)
2021-08-21
一款神仙接私活儿软件,吊到不行!
2021-07-31
基于 SpringBoot 的仿豆瓣平台【源码分享】
2021-07-18
干掉 Wordpress!这个开源建站神器有点吊!
2021-06-18
从朋友那里搞了 20 个实战项目,速领!
2021-06-12
如有收获,点个在看,诚挚感谢
工作流引擎核心设计思路!相关推荐
- JBPM工作流引擎内核设计思想及构架
1 前言 流程引擎内核仅是"满足Process基本运行"的最微小结构,而整个引擎则要复杂很多,包括"状态存储"."事件处理"."组 ...
- 工作流引擎的设计与实现
第四章 工作流引擎的设计与实现(一) (2009-03-24 17:26:26) 转载▼ 标签: 工作流数据模型 工作流数据结构 工作流定义 工作流实例 it 分类: 基于工作流的政务系统--设计 ...
- 基于J2EE的柔性工作流引擎的设计与实现
摘要 工作流的柔性问题日益成为研究的热点,本文在分析工作流和分布式计算技术J2EE的基础上,给出一个基于J2EE的柔性工作流引擎的设计方案及其关键部分的实现技术. 关键词 工作流引擎,柔性,J2EE ...
- 可自管理的分布式工作流引擎的设计与实现
<script type="text/javascript"></script> <script src="http://pagead2.g ...
- 工作流系列之可自管理的分布式工作流引擎的设计与实现
这篇文章是偶在清华读研究生时发表在国家核心期刊CIMS("Design and implementation of self-managed distributed workflow eng ...
- 轻量级工作流引擎的设计与实现
工作中,基于实际情况的需要,自研了一款工作流引擎,期间有不少收获,愿与同学们分享,听我娓娓道来- 一.什么是工作流引擎 简而言之,工作流引擎就是驱动工作流执行的一套代码. 至于什么是工作流.为什么要有 ...
- 说说 jBPM 工作流引擎的设计原理
1服务 API 设计 jBPM4 工作流引擎的核心 PVM 主要依靠 4 组服务 API : 流程定义服务 - Process Service. 流程执行服务- Execution Service. ...
- Salesforce平台支持多租户Multi tenant的核心设计思路
Multitenancy is the fundamental technology that clouds use to share IT resources cost-efficiently an ...
- 关于工作流引擎的设计讨论
说点我个人看法哈,一家之言,不一定准确,欢迎批评. 这个调度,我的理解还是根据一定的权限规则,以及流程定义,把工作流的报文按顺序传递给相关人员审阅,并兼顾异常事件查询等工作. 我觉得简单来说,就是根本 ...
最新文章
- go同一个目录下的go文件里面不能有多个package
- 图像聚类与检索的简单实现(一)
- MapReduce简述、工作流程
- C语言编写2048小游戏
- rxjava 被观察者_RxJava:从未来到可观察
- Linux网络管理实 验 指 导
- 解决Centos7 yum 出现could not retrieve mirrorlist 错误
- springboot2.4+nettyWebServerApplicationContext@15f51c50 has been closed already问题解决
- 如何在css中将图片横向摆放,css如何将图片横向平铺?
- STM8(STM8S003F3) Bootloader (IAP) 升级程序
- 多图预警~ 华为 ECS 与 阿里云 ECS 对比实战
- Android终端系统APP应用性能测试之响应速度流畅度
- u盘删不掉Android文件夹,U盘文件删不掉怎么办完全解决教程
- 【紫书】UVA714 抄书 Copying Books
- decltype和拖尾返回类型
- ARM(IMX6U)裸机之I.MX6ULL启动头文件详解(内部BOOT ROM、IVT + Boot data + DCD + led.bin)
- 使用ManagedWifi连接无线网络
- ios swift是静态语言吗
- php 两种递归方法
- 量子计算机算法与应用研究论文(转载务必注明出处)