如何优雅的设计工作流引擎(荣耀典藏版)_微型workflow-程序员宅基地

技术标签: java  mybatis  架构设计  # java基础  开发语言  

目录

前言

一、业务应用场景

二、工作流介绍

2.1 定义

2.2 工作流参考模型

2.3 工作流引擎特性

2.3 工作流引擎特性

2.5 工作流引擎和状态机的差异

三、开源工作流引擎

3.1.Activiti

3.2.Flowable

3.3.Camunda

3.4.jBPM

3.5.osworkflow

四、工作流引擎自研设计

4.1 使用开源工作流引擎的问题

4.2 自研引擎核心设计思路

4.2.1 引擎核心模块

4.3 具体实践

4.3.1引擎核心服务

 4.3.2流程定义服务

4.3.3.流程实例服务

4.3.4.流程任务节点服务

4.4 思考和扩展

五、总结


前言

大家好,我是程序缘--幻羽,我又来了!!

什么是工作流引擎(Workflow Engine )

例如开发一个系统,最关键的部分不是系统的界面,也不是和数据库之间的信息交换,而是如何根据业务逻辑开发出符合实际需要的程序逻辑并确保其稳定性、易维护性(模块化和结构化)和弹性(容易根据实际业务逻辑的变化作出程序上的变动,例如决策权的改变、组织结构的变动和由于业务方向的变化产生的全新业务逻辑等等)。 Workflow 引擎解决的就是这个问题:如果应用程序缺乏强大的逻辑层,势必变得容易出错(信息的路由错误、死循环等等)。

就好比一辆汽车,外表做得再漂亮,如果发动机有问题就只是一个摆设。应用系统的弹性就好比引擎转速方面的性能,加速到100 公里需要1 个小时(业务流程发生变动需要进行半年的程序修改)还能叫好车吗?引擎动不动就熄火(程序因为逻辑的问题陷入死循环)的车还敢开吗?

服务架构

面向服务的体系结构,是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。工作流引擎使得构建在各种这样的系统中的服务,可以以一种统一和通用的方式进行交互。

今天和大家一起学习如何优雅的设计工作流!!!!

一、业务应用场景

营销自动化平台可以支持不同用户生命周期的活动旅程策略配置 ,根据用户触发的不同活动行为,进行差异化的营销触达方案。同时各种类型活动的具体执行过程中也有不同的业务处理流程(比如审批流程和业务流转)。业务流程复杂多样,需求变更频繁,项目开发过程中会有以下痛点:

  1. 项目交付周期长: 一个完整的业务流程需要从头开始按版本迭代,开发时间长,成本高。

  2. 功能重复开发测试: 业务之间会掺杂着很多共性的流程,导致大量重复性开发测试工作,效率低。

  3. 维护成本高: 随着项目业务的逐步发展,业务流程逐步积累,可维护性下降,系统改动牵一发而动全身。

如何将业务逻辑从控制流中剥离出来,让产研人员更聚焦于业务的实现是需要重点解决的问题。而传统OA领域使用的是久经考验的业务流程管理解决方案 —— 工作流(Workflow) 。工作流是一套工业级的解决方案,由工作流管理联盟(WfMC)制定了一系列的标准。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

二、工作流介绍

2.1 定义

工作流(Workflow) —— 对工作流程及其各操作步骤之间业务规则的抽象,将流程中的工作组织逻辑和规则进行建模,交由计算机进行自动处理。

工作流的本质思想 是:通过预定义的工作流程模板,对现实活动进行实例化的过程 。简单说就是通过预设的格式或者可视化配置好流程的模板(比如一种分享活动的运行流程模板),使用时通过该模板构造出一个流程实例对象,通过实例对象完成活动运行跟踪和回溯。

2.2 工作流参考模型

WfMC工作流管理联盟为工作流制定了参考模型,其核心就是中间的工作流引擎,工作流引擎提供流程定义工具(接口1)、给使用者提供信息查询(接口2)、调用外部应用(接口3)、整合其他工作流(接口4)和监控管理(接口5)的能力。对于大多数工作流产品而言,重点关注的是接口1和接口2的实现。

2.3 工作流引擎特性

  1. 流程可视化

    提供可视化的流程搭建,流程视图查看能力,以及实时观测任务运行能力。

  2. 业务可编排复用

    将公共业务进行组件化,可以支持任务的自由编排,自由搭建出适合的业务的不同流程。

  3. 业务和控制分离

    将流程的控制(如流转、判断、循环、重试等)的任务交由工作流负责,让使用者聚焦于核心业务逻辑。

2.3 工作流引擎特性

对于工作流的类型没有专门的标准,按照流程任务节点特性可以分为:

  • 顺序工作流

顺序工作流的运行方式类似一种特定的流程图,上一个流程任务完成后依次进入下一个流程任务,过程不可逆。

  • 状态机工作流

状态机工作流侧重关注的是流程任务的状态,驱使任务状态发生变化的因素一般为外部事件,即事件驱动的方式,驱使任务节点从一个状态运行到另外一个状态,节点间可逆。

  • 规则驱动工作流

侧重于节点的运转规则,基于业务规则进行工作流程的执行,在处理具有明确目标但“规则”或规范级别不同的各种项目时,规则驱动的工作流非常有用。

可以看到不同类型的工作流不是完全割裂的,状态机工作流中也可以结合着条件和规则进行操作节点转换的过程。在软件开发中,一般会考虑结合状态机和规则驱动的工作流。

2.5 工作流引擎和状态机的差异

在之前的文章里面,我们有对状态机和工作流引擎 做过一次简单的对比 ,事实上,两者之间并不是一个完全对等的概念:

  1. 状态机 是系统状态以及这些状态之间转移和动作等行为的数学计算模型,

    工作流 是对整体工作流程及其各操作步骤之间业务逻辑和规则的抽象建模。

  2. 状态机 模式是事件驱动型,大多通过外部事件触发状态的自动流转;

    工作流引擎 更侧重于描述预定义流程任务完成之后的自动流转,可预测性会更强。

  3. 从适用场景的复杂性上看,

直接使用状态机 的方式可以清晰地描绘出所有可能的状态以及导致转换的事件,适用于解决单维度、复杂度不高的业务问题,发挥灵活轻便的特点;

工作流引擎 则更适合复杂的业务流程管理,解决如大型CRM复杂度更高的流程自动化问题,聚焦于改善整体业务流程的效率。

  1. 工作流引擎 是可以在状态机的结构模型基础上进行构建,事实上很多开源的工作流引擎也都是基于状态机的实现方式。

了解了工作流的基本特点和使用场景之后,我们来看一下比较流行的开源工作流引擎。

三、开源工作流引擎

开源框架对比:

经过对比,camunda 在功能方面比 flowable、activiti 流程引擎强大,性能和稳定性更突出。在开源流程引擎选型方面,camunda 是很好的方案之一。

3.1.Activiti

Activiti 由 Alfresco 公司开发,目前最高版本为 Activiti cloud 7.1.0。其中 activiti5 和 activiti6 的核心 leader 是 Tijs Rademakers,由于团队内部分歧,2017 年 Tijs Rademakers 离开团队,创建了后来的 Flowable。activiti6 以及 activiti5 代码则交接给 Salaboy 团队维护,activiti6 以及 activiti5 的代码官方已经暂停维护。往后 Salaboy 团队开发了 activiti7 框架,activiti7 内核使用的还是 activiti6,并没有为引擎注入更多的新特性,只是在 Activiti 之外的上层封装了一些应用。直到 Activiti cloud 7.1.0 版本,Activiti cloud 将系统拆分为 Runtime Bundle、Audit Service、Query Service、Cloud Connectors、Application Service、Notification Service。这些工作的主要目的其实就是为了上云,减少对 Activiti 依赖的耦合,需要使用 Activiti 的系统只需要通过调用 http 接口的方式来实现工作流能力的整合,将工作流业务托管上云。

3.2.Flowable

Flowable 是基于 activiti6 衍生出来的版本,目前最新版本是 v6.7.0。开发团队是从 Activiti 中分裂出来的,修复了一众 activiti6 的 bug,并在其基础上实现了 DMN 支持,BPEL 支持等。相对开源版,其商业版的功能会更强大。Flowable 是一个使用 Java 编写的轻量级业务流程引擎,使用 Apache V2 license 协议开源。2016 年 10 月,Activiti 工作流引擎的主要开发者离开 Alfresco 公司并在 Activiti 分支基础上开启了 Flowable 开源项目。Flowable 项目中包括 BPMN(Business Process Model and Notation)引擎、CMMN(Case Management Model and Notation)引擎、DMN(Decision Model and Notation)引擎和表单引擎(Form Engine)等模块。

3.3.Camunda

Camunda 基于 activiti5,所以其保留了 PVM,最新版本 Camunda7.17,开发团队也是从 activiti 中分裂出来的,发展轨迹与 Flowable 相似。通过压力测试验证 Camunda BPMN 引擎性能和稳定性更好。功能比较完善,除了 BPMN,Camunda 还支持 CMMN(案例管理)和 DMN(决策自动化)。Camunda 不仅带有引擎,还带有非常强大的工具[6],用于建模、任务管理、操作监控和用户管理。

3.4.jBPM

jBPM 由 JBoss 公司开发,目前最高版本 7.61.0.Final,不过从 jBPM5 开始已经跟之前不是同一个产品了,jBPM5 的代码基础不是 jBPM4,而是从 Drools Flow 重新开始,基于 Drools Flow 技术在国内市场上用的很少,jBPM4 诞生的比较早,后来 jBPM4 创建者 Tom Baeyens 离开 JBoss 后,加入 Alfresco 后很快推出了新的基于 jBPM4 的开源工作流系统 Activiti,另外 jBPM 以 Hibernate 作为数据持久化 ORM,而 Hibernate 也已不是主流技术。

3.5.osworkflow

osworkflow 是一个轻量化的流程引擎,基于状态机机制,数据库表很少,osworkflow 提供的工作流构成元素有:步骤(step)、条件(conditions)、循环(loops)、分支(spilts)、合并(joins)等,但不支持会签、跳转、退回、加签等这些操作,需要自己扩展开发,有一定难度。如果流程比较简单,osworkflow 是很好的选择。

四、工作流引擎自研设计

4.1 使用开源工作流引擎的问题

  1. 开源工作流最大的优势是可以借助开源的资源,开箱即用,功能全面,但是与之带来的是附带的配置和表数量比较多的维护问题。以Activiti为例,使用Activiti7.0版本至少要引入二十多张表,虽然说看似是无侵入的方式,但是系统演进和维护过程中有一定的成本。特别是业务流程实例很多的时候,开发人员需要对表逻辑有更深的把控。

  2. 由于业务的客观独特性,作为业务流程组件,一般都需要根据自身业务进行二次开发适配。比如需要根据自身组织架构,进行流程节点用户角色权限的管控;将自身的业务能力插件化,加入工作流程配置中,进行拦截回调等。

4.2 自研引擎核心设计思路

4.2.1 引擎核心模块

回归工作流的本质, 工作流是通过预定义的流程模板,对现实活动进行实例化的过程。一个基本的工作流引擎主要包括三大核心部分:

  • 流程模板创建

    根据业务规则和逻辑,创建流程模板,设置每一个节点的操作和变更路径。基于模板创建,可以延伸出流程设计器、插件式节点,多样化的模板文件格式、模板持久化等。

  • 流程实例发布

    根据流程模板,创建一个流程实例,流程模板和流程实例的关系类似类和对象的关系。比如说工单系统管理员定义好一个审批流模板(流程模板),用户点击创建一个工单(流程实例)。基于流程实例发布,又可以延伸出实例实时观测,节点变迁记录回溯,实例状态持久化,失败重试,事务控制等。

  • 任务流程执行

    创建好流程实例之后,流程实例只需要按照流程模板的定义独立执行各自实例的任务,不同的实例之间互不影响,完成各自实例的生命周期。

 4.2.2 引擎核心设计

  1.  应用容器启动时,加载流程引擎环境配置,包括解析器构造,流程引擎上下文,流程定义文件路径等。
  2. 读取定好的流程定义文件,进行流程节点解析,构建好执行上下文,将流程节点放到内存缓存中。
  3. 业务侧进行流程创建,启动一个新的流程实例,同时将业务流程和流程实例进行绑定。
  4. 运行流程实例各个节点,将每个流程节点进行持久化保存。

4.3 具体实践

4.3.1引擎核心服务

引擎操作的主要对外接口,包括启动流程实例,和获取相关流程定义模板,流程实例,流程节点的服务。

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();
}

 4.3.2流程定义服务

主要是针对流程定义模板的创建和发布,可以根据具体的实现类来支持不同的创建方式。

public interface ProcessService {  
   /**
     * 创建流程定义模板
     *
     */
    void create(String definition);
 
   /**
     * 发布流程定义模板
     *
     */
    void deploy(String fileName);
 
    /**
     * 获取流程key对应的流程定义
     */
    FlowProcess getProcessByDefKey(String processDefKey);
}

4.3.3.流程实例服务

提供流程实例创建持久化和流程实例执行的入口。

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);
}

4.3.4.流程任务节点服务

提供流程节点具体每个任务的创建和查询。

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 思考和扩展

  1. 流程定义解析性能。

    由于目前设计是在应用启动时对所有的流程定义文件进行加载和解析,流程定义文件过多时会影响应用启动速度,可以通过多线程解析和懒加载(使用时解析)两种方式进行优化。

  2. 流程定义版本兼容性。

    由于业务流程不是一成不变的,在项目发展过程中会不断进行迭代,需要对前面不同的流程进行兼容。

  3. 流程节点插件化和编排能力 。

    将基础服务进行提取公用,以支持绘制不同流程的插件化和编排能力。

  4. 流程执行监控能力。

    对流程任务节点执行情况进行埋点上报,系统自动进行监测告警。

五、总结

工作流的本质思想是通过预定义的工作流程模板,对现实活动进行实例化的过程。一般需要具备流程可视化、业务可编排复用、 业务和控制分离的基本能力。一般常见的工作流分为顺序工作流、状态机工作流和规则驱动工作流,开源工作流框架中最常见的是状态机工作流,利用事件驱动的方式,驱使流程运转。

同时简单介绍了业界比较流行的几种开源工作流引擎的特点,结合开源工作流引擎的特点的问题,并且针对多样化和迭代频繁的业务流程, 以工作流的本质思想为出发点,我们自研了一套轻量级的工作流引擎,分享了在实践过程中的设计思路和总结思考。

 只有当你开始,你才会到达你的理想和目的地,只有当你努力,
你才会获得辉煌的成功,只有当你播种,你才会有所收获。只有追求,
才能尝到成功的味道,坚持在昨天叫立足,坚持在今天叫进取,坚持在明天叫成功。欢迎所有小伙伴们点赞+收藏!!!

都看到这里了,就点个 吧。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_48321993/article/details/126031222

智能推荐

874计算机科学基础综合,2018年四川大学874计算机科学专业基础综合之计算机操作系统考研仿真模拟五套题...-程序员宅基地

文章浏览阅读1.1k次。一、选择题1. 串行接口是指( )。A. 接口与系统总线之间串行传送,接口与I/0设备之间串行传送B. 接口与系统总线之间串行传送,接口与1/0设备之间并行传送C. 接口与系统总线之间并行传送,接口与I/0设备之间串行传送D. 接口与系统总线之间并行传送,接口与I/0设备之间并行传送【答案】C2. 最容易造成很多小碎片的可变分区分配算法是( )。A. 首次适应算法B. 最佳适应算法..._874 计算机科学专业基础综合题型

XShell连接失败:Could not connect to '192.168.191.128' (port 22): Connection failed._could not connect to '192.168.17.128' (port 22): c-程序员宅基地

文章浏览阅读9.7k次,点赞5次,收藏15次。连接xshell失败,报错如下图,怎么解决呢。1、通过ps -e|grep ssh命令判断是否安装ssh服务2、如果只有客户端安装了,服务器没有安装,则需要安装ssh服务器,命令:apt-get install openssh-server3、安装成功之后,启动ssh服务,命令:/etc/init.d/ssh start4、通过ps -e|grep ssh命令再次判断是否正确启动..._could not connect to '192.168.17.128' (port 22): connection failed.

杰理之KeyPage【篇】_杰理 空白芯片 烧入key文件-程序员宅基地

文章浏览阅读209次。00000000_杰理 空白芯片 烧入key文件

一文读懂ChatGPT,满足你对chatGPT的好奇心_引发对chatgpt兴趣的表述-程序员宅基地

文章浏览阅读475次。2023年初,“ChatGPT”一词在社交媒体上引起了热议,人们纷纷探讨它的本质和对社会的影响。就连央视新闻也对此进行了报道。作为新传专业的前沿人士,我们当然不能忽视这一热点。本文将全面解析ChatGPT,打开“技术黑箱”,探讨它对新闻与传播领域的影响。_引发对chatgpt兴趣的表述

中文字符频率统计python_用Python数据分析方法进行汉字声调频率统计分析-程序员宅基地

文章浏览阅读259次。用Python数据分析方法进行汉字声调频率统计分析木合塔尔·沙地克;布合力齐姑丽·瓦斯力【期刊名称】《电脑知识与技术》【年(卷),期】2017(013)035【摘要】该文首先用Python程序,自动获取基本汉字字符集中的所有汉字,然后用汉字拼音转换工具pypinyin把所有汉字转换成拼音,最后根据所有汉字的拼音声调,统计并可视化拼音声调的占比.【总页数】2页(13-14)【关键词】数据分析;数据可..._汉字声调频率统计

linux输出信息调试信息重定向-程序员宅基地

文章浏览阅读64次。最近在做一个android系统移植的项目,所使用的开发板com1是调试串口,就是说会有uboot和kernel的调试信息打印在com1上(ttySAC0)。因为后期要使用ttySAC0作为上层应用通信串口,所以要把所有的调试信息都给去掉。参考网上的几篇文章,自己做了如下修改,终于把调试信息重定向到ttySAC1上了,在这做下记录。参考文章有:http://blog.csdn.net/longt..._嵌入式rootfs 输出重定向到/dev/console

随便推点

uniapp 引入iconfont图标库彩色symbol教程_uniapp symbol图标-程序员宅基地

文章浏览阅读1.2k次,点赞4次,收藏12次。1,先去iconfont登录,然后选择图标加入购物车 2,点击又上角车车添加进入项目我的项目中就会出现选择的图标 3,点击下载至本地,然后解压文件夹,然后切换到uniapp打开终端运行注:要保证自己电脑有安装node(没有安装node可以去官网下载Node.js 中文网)npm i -g iconfont-tools(mac用户失败的话在前面加个sudo,password就是自己的开机密码吧)4,终端切换到上面解压的文件夹里面,运行iconfont-tools 这些可以默认也可以自己命名(我是自己命名的_uniapp symbol图标

C、C++ 对于char*和char[]的理解_c++ char*-程序员宅基地

文章浏览阅读1.2w次,点赞25次,收藏192次。char*和char[]都是指针,指向第一个字符所在的地址,但char*是常量的指针,char[]是指针的常量_c++ char*

Sublime Text2 使用教程-程序员宅基地

文章浏览阅读930次。代码编辑器或者文本编辑器,对于程序员来说,就像剑与战士一样,谁都想拥有一把可以随心驾驭且锋利无比的宝剑,而每一位程序员,同样会去追求最适合自己的强大、灵活的编辑器,相信你和我一样,都不会例外。我用过的编辑器不少,真不少~ 但却没有哪款让我特别心仪的,直到我遇到了 Sublime Text 2 !如果说“神器”是我能给予一款软件最高的评价,那么我很乐意为它封上这么一个称号。它小巧绿色且速度非

对10个整数进行按照从小到大的顺序排序用选择法和冒泡排序_对十个数进行大小排序java-程序员宅基地

文章浏览阅读4.1k次。一、选择法这是每一个数出来跟后面所有的进行比较。2.冒泡排序法,是两个相邻的进行对比。_对十个数进行大小排序java

物联网开发笔记——使用网络调试助手连接阿里云物联网平台(基于MQTT协议)_网络调试助手连接阿里云连不上-程序员宅基地

文章浏览阅读2.9k次。物联网开发笔记——使用网络调试助手连接阿里云物联网平台(基于MQTT协议)其实作者本意是使用4G模块来实现与阿里云物联网平台的连接过程,但是由于自己用的4G模块自身的限制,使得阿里云连接总是无法建立,已经联系客服返厂检修了,于是我在此使用网络调试助手来演示如何与阿里云物联网平台建立连接。一.准备工作1.MQTT协议说明文档(3.1.1版本)2.网络调试助手(可使用域名与服务器建立连接)PS:与阿里云建立连解释,最好使用域名来完成连接过程,而不是使用IP号。这里我跟阿里云的售后工程师咨询过,表示对应_网络调试助手连接阿里云连不上

<<<零基础C++速成>>>_无c语言基础c++期末速成-程序员宅基地

文章浏览阅读544次,点赞5次,收藏6次。运算符与表达式任何高级程序设计语言中,表达式都是最基本的组成部分,可以说C++中的大部分语句都是由表达式构成的。_无c语言基础c++期末速成