1 什么是流程引擎
流程引擎是一个底层撑持平台,是为提供流程解决而开发设计的。流程引擎和流程利用,以及应用程序的关系如下图所示。
常见的撑持场景有:Workflow、BPM、流程编排等。本次分享,次要从 BPM 流程引擎切入,介绍流程引擎的架构设计办法。
1.1 什么是流程
简略来说,流程就是一系列流动的组合。比方,用于企业办公的 OA 零碎中,就存在大量的申请审批类的流程。在生产制造业,有大量的从销售端的订单,到生产制作,再到签收回款的生产销售流程。在机器学习畛域,有亚马逊 AWS Sagemaker 的大数据处理、机器学习的利用。综上,流程是一个概念,在和具体实现联合时,就产生了不同的流程产品,如 DevOps、Spring Data Stream 等。
在流程实现方面,次要能够分为 2 种实现形式,一种是用代码实现,比方:用代码实现一个加班申请,那么就要本人对接 SSO 进行单点登录,通过接口拿到发起人和审批人的信息,同时保留表单数据。另一种形式是应用流程引擎来实现,流程引擎对接利用场景所需数据,如加班申请,流程引擎对接 SSO、OU、审批人配置、权限等,实现这样一个流程,只须要关怀流程配置、流程节点和流程表单即可,流程流转以及流程的数据处理,都通过流程引擎来实现。
流程引擎能够疾速落地流程实现,这也是流程引擎存在的价值。
1.2 什么是引擎
一般而言,引擎是一个程序或一套零碎的反对局部。常见的程序引擎有游戏引擎、搜索引擎、杀毒引擎等。引擎是脱离具体业务场景的某一类业务场景的高度形象和封装。
比方,某 OA 公司,封装了一套审批用的 workflow,施行人员只须要配置流程和表单即可交付我的项目。再比方,美国某公司做了一个 AI 引擎做 NBA(Next Best Action)举荐,封装了举荐畛域的罕用算法,在不同的场景主动抉择和组合多种算法,进行智能举荐。
1.3 流程设计器
流程设计器是流程和引擎的连贯方,用户通过流程设计器,将某种 layout 和 rule 固化成某种流程,而后通过数据和数据上下文,应用流程引擎主动依照某种固化的流程进行执行。
我将目前见到的流程设计器的实践根底,分为以下三类:1,自定义系;2,UML 中的流动图系;3,BPMN 系。
1.3.1 自定义系
用于 Sagemaker 等场景的 AWS Step Function(自定义流程节点)
1.3.2 UML Activity Diagram
Flowportal BPM 的流程设计器
1.3.3 BPMN 系
activiti 的流程设计器
炎黄盈动的流程设计器
题外话:炎黄盈动的流程设计器,和 processon 中的流程设计器界面简直一样,因为实质上是一家的。
2 流程引擎的利用
2.1 Workflow
工作流治理联盟 (Workflow Management Coalition,WfMC) 作为工作流治理的标准化组织而成立。
WfMC 对工作流给出定义为:工作流是指一类可能齐全主动执行的经营过程,依据一系列过程规定,将文档、信息或工作在不同的执行者之间进行传递与执行。
在 workflow 中,流程引擎次要用于撑持流程审批和数据流转,利用场景十分宽泛。
国外产品(开源或商用)通常需要和操作比较简单,不会有国内的需要那么简单。国内的产品,经验了泛滥客户的锻炼,性能目前都比拟弱小。
一般而言,workflow 应用场景最多的是 OA 产品。在 OA 办公中,蕴含了企业办公中的大量元素,这些元素足够造成特定的产品,比方门户零碎、挪动办公。在 OA 的我的项目落地过程中,联合行业、业务侧重点又能够造成行业解决方案和专题计划。
以下是某 OA 公司产品和解决方案。
2.2 BPM(Business Process Management)
Workflow 次要是解决审批和数据流转,而 BPM 次要是解决端到端、信息孤岛等问题而存在的。大多数用 BPM 产品的客户,都是在 BPM 根底上进行零碎搭建,比方在 BPM 下面搭建 OA、CRM、HR 等零碎。
BPM 的应用场景,比 Workflow 更宽泛,BPM 产品中蕴含大量的和第三方零碎交互的组件和自定义 SQL、代码组件。比方,BPM 零碎中的文件触发器,能够在海关等交互场景下,通过监控 FTP 服务器中的文件,主动触发流程实例;能够通过定时器 Timer,主动每日执行数据同步,并通过 Mail 节点将同步后果告诉到相干经营成员等。
BPM 的利用,能够依照执行前、执行中和执行起初划分。
2.3 流程编排
流程编排是脱离流程业务畛域的更高一层形象,应用方能够通过流程编排零碎,联合本人的业务场景进行业务定制。比方,能够将相干业务代码,封装成 function,而后通过云厂商平台的 FAAS 平台,将不同业务的 function 进行关联和调度,从而实现某项工作。
3 流程引擎的架构设计
鉴于一些敌人可能没有应用和接触过流程引擎,先介绍流程引擎的组成单元,再介绍基于某个 BPM 产品的我的项目是如何进行开发的。咱们通过 BPM 我的项目开发,对流程引擎的作用有个初步的意识。
3.1 BPM 流程引擎的组成单元
- 组织、角色、用户、成员的组织架构托管;
- 流程资源文件的配置、校验、存储和执行,对不同的流程节点,流程引擎主动联合配置、数据处理其对应的业务逻辑,流程数据主动解决;
- 表单配置、数据绑定,表单数据的依据流程配置主动解决;
- 通用的数据接口;
3.1.1 组织架构的设计
3.1.2 流程设计器
流程设计器蕴含左侧的分组节点列表,和右侧的画布。左侧的节点能够如下进行设计。
问题:对于一个 XML 或 JSON 格局的流程图,如何进行解析?
不同的节点,依照不同的业务场景,配置不同的配置项。比方,对于 Human Node 须要配置审批人,配置审批环节的展现表单,审批环节可能批改哪些字段,哪些字段的批改要进行留痕等。
3.1.3 表单设计器
这种是依照表单相干数据表,生成出一个表单,而后对表单字段进行配置和数据绑定。
这种是 Drag&Drop 控件,而后配置控件的属性,如绑定字段等。
这种是 Drag&Drop 控件,无需关联数据库表字段的表单
数据表生成表单的概要流程如下图所示。
拖拽控件绑定数据表字段的概要流程如下。
拖拽控件无需绑定数据表字段的概要流程。应用 NoSQL 的 Document 记录或应用 RDS 提供的 JSON 类型进行保留会比拟不便。
3.1.4 接口设计
联合 Activity 的接口设计,如下图所示
一些零碎在创立一个流程工作的时候,要先依照流程模板先创立一个利用示例,再关联发起人和备注,调用 RuntimeService,执行到 StartNode,这类设计因人而异,这么做略显繁琐。
3.2 基于流程引擎的我的项目开发实际
3.2.1 流程我的项目实际流程
- 确定组织架构
- 确定流程,包含流程布局、审批人设置、权限
- 确定表单信息(字段、类型、数据源、校验规定)和表单款式
- 确定页面布局、款式、数据字段、搜寻、导入、导出
- 报表
3.2.2 组织架构
组织架构实现,有两种办法,一种是依照维度进行数据管理,另一种是在同一棵组织架构树下进行治理。
依照团体、公司、部门、用户等不同维度,进行数据管理,比拟常见,这里不做探讨。下图为按维度保护数据的示例。
依照同一棵组织架构树进行数据保护,界面个别显示为左树右表。大多数商业化产品,都会将此组织架构树进行内存缓存,以不便审批人查找、开窗抉择 OrgUnit、Role、User、Member 等场景。Member 的引入是为了解决一人多职等场景。个别发动流程的时候,须要带出发起人领有的 Member 列表,从而后续节点取适合的审批人。
对于组织架构而言,须要思考,零碎自身要具备 OU 存储的能力,对于没有组织架构的用户,能够间接在零碎的组织架构中新建组织架构。同时,对于已有零碎的客户,能够通过组织架构数据同步来进行数据主动保护。对于用 AD 域外部管控的客户来说,须要具备 AD 域身份认证的能力。对于简单场景,比方用户是 SaaS 化等简单场景,组织架构也须要在零碎外部,反对应用 API 的形式来获取组织信息。
所以在组织架构设计的时候,要应用插件的形式来做,具体应用哪种插件,能够在配置文件中进行配置。以下为一个商业产品的组织架构操作界面示例。
常见的组织架构操作还有组织架构同步,比方流程零碎同步微信企业号、钉钉等,这里不再开展。
3.2.3 流程设计
咱们设想的流程,可能是向上面的这种简略流程。
而理论我的项目,碰到的流程,个别是如下图所示的情景。
初步看几个流程的模型文件是什么样的,先有个印象。
<?xml version="1.0" encoding="UTF-8" ?>
<definitions id="definitions"
targetNamespace="http://activiti.org/bpmn20"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn">
<process id="vacationRequest" name="Vacation request">
<startEvent id="request" activiti:initiator="employeeName">
<extensionElements>
<activiti:formProperty id="numberOfDays" name="Number of days" type="long" value="1" required="true"/>
<activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
<activiti:formProperty id="vacationMotivation" name="Motivation" type="string" />
</extensionElements>
</startEvent>
<sequenceFlow id="flow1" sourceRef="request" targetRef="handleRequest" />
<userTask id="handleRequest" name="Handle vacation request" >
<documentation>
${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).
</documentation>
<extensionElements>
<activiti:formProperty id="vacationApproved" name="Do you approve this vacation" type="enum" required="true">
<activiti:value id="true" name="Approve" />
<activiti:value id="false" name="Reject" />
</activiti:formProperty>
<activiti:formProperty id="managerMotivation" name="Motivation" type="string" />
</extensionElements>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow2" sourceRef="handleRequest" targetRef="requestApprovedDecision" />
<exclusiveGateway id="requestApprovedDecision" name="Request approved?" />
<sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}</conditionExpression>
</sequenceFlow>
<task id="sendApprovalMail" name="Send confirmation e-mail" />
<sequenceFlow id="flow4" sourceRef="sendApprovalMail" targetRef="theEnd1" />
<endEvent id="theEnd1" />
<sequenceFlow id="flow5" sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'false'}</conditionExpression>
</sequenceFlow>
<userTask id="adjustVacationRequestTask" name="Adjust vacation request">
<documentation>
Your manager has disapproved your vacation request for ${numberOfDays} days.
Reason: ${managerMotivation}
</documentation>
<extensionElements>
<activiti:formProperty id="numberOfDays" name="Number of days" value="${numberOfDays}" type="long" required="true"/>
<activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" value="${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
<activiti:formProperty id="vacationMotivation" name="Motivation" value="${vacationMotivation}" type="string" />
<activiti:formProperty id="resendRequest" name="Resend vacation request to manager?" type="enum" required="true">
<activiti:value id="true" name="Yes" />
<activiti:value id="false" name="No" />
</activiti:formProperty>
</extensionElements>
<humanPerformer>
<resourceAssignmentExpression>
<formalExpression>${employeeName}</formalExpression>
</resourceAssignmentExpression>
</humanPerformer>
</userTask>
<sequenceFlow id="flow6" sourceRef="adjustVacationRequestTask" targetRef="resendRequestDecision" />
<exclusiveGateway id="resendRequestDecision" name="Resend request?" />
<sequenceFlow id="flow7" sourceRef="resendRequestDecision" targetRef="handleRequest">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'true'}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow8" sourceRef="resendRequestDecision" targetRef="theEnd2">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'false'}</conditionExpression>
</sequenceFlow>
<endEvent id="theEnd2" />
</process>
</definitions>
一个屏幕截图都截不完的流程,如果用代码去实现整个流程,其工作量和效率,可想而知。而理论做我的项目,应用基于流程引擎的产品来做我的项目的时候,只须要确定节点、节点配置、数据配置和权限即可。
问题:个别流程,都带有邮件告诉的节点,如何实现邮件告诉节点?请思考以下情景。
流程流转和执行的时候,会遇到各种状况的谬误,比方找不到审批人等,此时流程引擎要对数据做 rollback,而邮件告诉节点的业务逻辑曾经执行过了。
权限方面,对于流程资源,哪些部门能够申请,哪些角色不可申请,都应该做流程管制。而在流程执行过程中,流程数据、不是途程的相干人也都不应该看到流程,解决过流程的审批人,不能够再对流程进行解决等,都是权限方面要思考的问题。
3.2.4 表单设计
如下图所示的表单,能够剖析以下,一个流程表单有多个主表信息和多个子表信息。一般而言,如果是通过流程引擎做非流程的数据处理,子表通过主表 ID 来做关联,如果通过流程引擎做流程的数据处理,子表和主表通过 TaskId 来做关联。以下为示例。
流程零碎须要表单设计器,一个流程的不同节点能够挂接不同的表单,以不便不同角色的人关注不同维度的流程信息
3.2.5 页面设计
一般而言,对于流程的发动、审批、历史记录等,都是通用的零碎界面。而一些业务场景,须要独自做列表界面,以方便使用。对于已有门户零碎的客户,须要交融其界面款式。以下为已经做过的我的项目示例。
3.2.6 报表
因为不是所有客户都有报表零碎,所以流程零碎须要具备一个根本的报表性能。下图为示例。
有报表零碎的客户,能够应用其商业版报表零碎,获取(间接取、数仓)数据进行展现。常见的报表零碎有 FineReport、Tableau、PowerBI 等。
3.3 BPM 流程引擎架构设计
3.3.1 流程引擎的架构设计
3.3.2 发动流程
流程引擎处理过程
执行节点处理过程
问题:在流程引擎处理过程中,如果一个节点有多条连线,如何寻找 FromNodeId 是某个 Node 的连线?
人工解决时,指定连线 text
3.4 流程引擎架构设计
3.4.1 业务辨认
- 辨认业务场景中的配置项,应用汇合或分组的形式,让业务可配置
- 撑持业务流程过程的可配置化
- 撑持业务场景中的数据,主动解决
3.4.2 流程引擎的实现
- 资源相干服务,资源加载,资源保留,资源加密等
- 配置项相干服务
- PVM 虚拟机的实现,即通过某个节点(发动时为开始节点)作为初始节点,依照某个连线的 action 进行节点的主动执行的虚拟机
- 数据配置、数据权限
- 流程数据和业务数据的主动解决
4 商业机会
- Business Process Analysis (BPA) 流程剖析,帮忙企业进行流程调整和优化
- Process Assets Library(PAL)流程资产库,对企业流程进行知识化积淀,将制度和流程落地做绑定,让审批人通晓流程中对应的职责
- Process Simulate 流程模仿,自动化测试
- Process Forecast 流程预测
- 低代码平台
- 更宽泛的机会,在于业务畛域 + 流程引擎,比方:DevOps、RPA、利用与服务编排、数据编排、FaaS 编排等。
作者:马瑞