微型工作流引擎设计

微型工作流引擎设计

一、前言

提到工作流很多人就会想到OA,的确OA就是典型的工作流的应用,但是工作流并不仅仅局限于OA,工作流应该算是基础框架软件,主要用于流程的重组和优化,它有广阔的应用领域。在java下有很多优秀的开源工作流可以选择比如activit5、jpbm4等,在.net下却几乎找不到令人满意的工作流引擎可用。当然不是说.net下没有开源的只是有些国产开源的但看了代码后就一点兴趣都没有了,且不说代码质量如何,还引入了一大堆的东西,想在项目中应用也是非常困难。鉴于此我还是决定自己开发一款.NET微型工作流引擎。

二、基本说明

为什么叫微型工作流引擎?就是超轻量级,以方便在项目中轻便的使用,比如只有一个类库dll,大小也就几百k到1M左右,不过我们要先回过头来看看工作流系统,它实在是太大了,它应该包括: 
    1、工作流引擎 
    2、工作流设计器 
    3、工作流管理系统 
    4、表单设计器

目前来说的我只实现了核心引擎,流程定义也只能先在xml中编辑然后读取到引擎中或者直接定义到数据库中,但整个流程是能够正常流转。至于流程设计器、表单设计器、工作流管理系统这个我有精力了再慢慢开发。这里我完成的只是很小的一块,但是是工作流的核心,可以很方便的嵌入到业务系统中应用。

引擎主要提供了对于工作流定义的解析以及流程流转的支持。工作流定义文件描述了业务的交互逻辑,工作流引擎通过解析工作流定义文件按照业务的交互逻辑进行业务的流转,工作流引擎通常通过参考某种模型来进行设计,通过调度算法来进行流程的流转(流程的启动、终止、挂起、恢复等),通过各种环节调度算法来实现对于环节的流转(环节的合并、分叉、选择、条件性的选择等)。

三、初步印象

1、从概念开始解释估计大家都会看不下去了。我们先拿一个简单实例来看看,新建一个项目,引用我的工作流引擎类库(Chitu.Bpm.dll,取名为赤兔)。 
在项目启动时配置流程引擎(Global.asax.cs中),如下:

//初始化流程引擎
BpmConfiguration
    .Instance()
    .Config(@"C:\Configration\BpmConfig.xml")
    .Start();

在项目中使用时,比如新建流程定义:

//取得工作流上下文
var bpm = new BpmContext()
    .UseTransaction(true)
    .SetActor("萧秦");

//新增流程定义
bpm.NewProcessDefinition("请假流程")
    .SetXmlFile(@"C:\Definition\demo1.xml")
    .SetCategory("分类1")
    .SetEffectDate(DateTime.Now)
    .SetExpireDate(DateTime.Now.AddDays(180))
    .SetMemo("memo1")
    .Create()  //创建流程定义,只生成bpm_definition_process表
    .Parse()   //解析xml
    .Deploy(); //发布流程

启动流程:

//启动流程
var process = bpm.NewProcessIntance("请假流程ID", "萧秦(业务ID)");   //创建流程实例
process.SetVariable("流程变量1", "值1");                     //设置流程变量
process.Start();

人工任务节点转交下一步:

//任务完成
var task = bpm.LoadTaskInstance("任务ID");
task.SetVariable("任务变量2", "xx");
task.Signal(); //触发令牌流转

所有的操作都通过Facade模式集中到BpmContext中,操作简单方便。

2、接下来我们先看看流程定义的XML,以下是我捏造的一个流程,以便把各种节点都放进去了。

<?xml version="1.0" encoding="UTF-8"?>

<process name="样板房装修流程">

  <start name="装修申请">
    <transition to="装修方案设计" >
      <action class="Namespace.MyActionHandler"></action>
    </transition>
  </start>

  <task name="装修方案设计">
    <transition to="装修方案审核">
      <action script="log.Debug(‘装修方案审核 action test‘);"></action>
    </transition>
  </task>

  <decision name="装修方案审核">
    <transitions>
      <transition to="装修筹备"     condition-expression="variable.pass == true"></transition>
      <transition to="装修方案设计" condition-expression="variable.pass != true"></transition>
    </transitions>

    <events>
      <action event="enter" class="enterHandlerClass"></action>
      <action event="leave" class="leaveHandlerClass"></action>
    </events>

    <assignments>
      <assignment owner="{process.starter}"></assignment>
    </assignments>

    <variables>
      <variable type="boolean" name="IsPass" access="read,required"></variable>
    </variables>
  </decision>

  <fork name="装修筹备">
    <transition to="装修合同签定"></transition>
    <transition to="等待装修工人到位"></transition>
    <transition to="装修材料预算"></transition>
  </fork>

  <sign name="装修合同签定"  necessary="false" async="true">
    <transition to="装修施工"></transition>
  </sign>

  <wait name="等待装修工人到位">
    <transition to="装修施工"></transition>
  </wait>

  <task name="装修材料预算">
    <transition to="材料采购子流程"></transition>
  </task>

  <subflow name="材料采购子流程">
    <transition to="装修施工"></transition>
  </subflow>

  <join name="装修施工">
    <transition to="施工验收/付款"></transition>
  </join>

  <auto name="施工验收/付款">
    <transition to="装修完成"></transition>
  </auto>

  <end name="装修完成">
  </end>

  <events>
    <action event="process-start" class="TestStartHandler"></action>
    <action event="process-end" class="TestEndHandler"></action>
  </events>

  <variables>
    <variable type="string" name="start_id" access="readonly,required"></variable>
    <variable type="string" name="start_person"></variable>
  </variables>
</process>

定义的根节点为流程(process),流程下为各个任务节点(node),任务节点分为: 
start       开始节点 
auto       自动节点 
task       人工节点 
decisioin 决策节点 
fork        发散节点 
join        聚合节点 
sublfow  子流程节点 
sign       会签节点 
wait       等待节点
end        结束节点

任务节点下可以包括路由(transition)动作(action)及人员分配(assignment)变量定义(variable) 
其中action包括几种类型:1、class 2、script 3、sql 4、webservice 5、expression 
在script或expression中可以直接访问process.xxx属性或task.xxx属性或variable.xxx简化了动态c#语句的使用。 
当然XML定义中还有很多其它的属性定义我这里也没有都列出来,以后用到了再仔细说。

3、关于数据库设计,这里仅仅是流程流转核心所需要的表,表之间都没有拉关系 

四、部分功能剖析

a、我把它划分为主要的几大模块: 引擎配置、流程定义、实例流转、日志处理、计划任务 
        引擎配置:配置引擎实例的数据库连接、日志配置、参数设定等。 
        流程定义:利用xml来描述流程,主要定义任务节点,路由、动作事件、变量、人员分配等 
        实例流转:根据定义运行流程实例 
        日志处理:输出日志 
        任务计划:会启动一个服务,用于处理比如延时启动,任务过期等

b、流转中的关键性类设计包括: 
        1、流程对象(Process) 
        2、工作任务(Task) 
        3、路由(Trasition) 
        4、令牌(Token) 
        5、事件总线与动作处理 (EventBus、ActionHandler) 
        6、人员分配及委托机制(Assignment、Depute) 
        7、流程回退处理(RollbackService) 
        8、消息服务(NotifyService)

c、通常引擎控制流程调度流转核心的调度算法主要有FSM以及PetriNet两种,基于调度算法来完成流程的流转: 
        1、FSM(有限状态机) 
        FSM 的定义为包含一组状态集(states)、一个起始状态(start state)、一组输入符号集(alphabet)、一个映射输入符号和当前状态到下一状态的转换函数(transition function)的计算模型。当输入符号串,模型随即进入起始状态。它要改变到新的状态,依赖于转换函数。在有限状态机中,会有有许多变量,例如,状态机有很多与动作(actions)转换(Mealy机)或状态(摩尔机)关联的动作,多重起始状态,基于没有输入符号的转换,或者指定符号和状态(非定有限状态机)的多个转换,指派给接收状态(识别者)的一个或多个状态,等等。遵循FSM流程引擎通过状态的切换来完成流程的流转。 
        2、PetriNet 
        信息流的一个抽象的、形式的模型。指出一系统的静态和动态性质。PetriNet通常表示成图。遵循PetriNet流程引擎通过令牌来决定流程的流转。 
        我采用的是第二种PetriNet算法。用Token来表示当前实例运行的位置,也利用token在流程各个点之间的转移来表示流程的推进,如下图所示: 
      
      令牌流转逻辑,我把以下类方法都做一个简化省略了路由选择及节点处理细节,好让大家明白令牌的流转:

//令牌Token类中Signal
public void Signal()
{
    fromTask.Leave(executeContext);
}

//任务Task类中的Leave
public void Leave(ExecutionContext executionContext)
{
    transition.Take(executionContext);
}

//路由Transition类中的Take
public void Take(ExecutionContext executionContext)
{
    toTask.Enter(executionContext);
}

//任务Task类中的Enter
public void Enter(ExecutionContext executionContext)
{
    Run(executionContext);
}

至此令牌成功的从一个节点转移到下一个节点了,令牌的流转是工作流的关键,当然不同的节点处理是有所不同的,其中最复杂的当数发散节点及聚合节点了。这里就介绍到这里,不再给大家详细介绍了。

d、目前我引擎中实现的主要包括以下功能: 
    1、解释过程定义 
    2、控制过程实例—创建、激活、挂起、终止等 
    3、控制流程调度流转 
    4、自定义动作及事件发布 
    5、流程变量及工作变量处理 
    6、任务计划,比如延时启动,任务过期等 
    7、委托服务,委托代办 
    8、回退服务,回退到任意节点或召回 
    9、消息服务,比如认领通知、待办提醒、催办消息… 
    10、流程任务监控服务 
    11、日志处理及历史记录 
    12、任务分配与认领       
    13、参与者组织模型接口

五、总结

目前我的这款工作流引擎还在继续完善当中,我总结下它的优缺点: 
优点: 
1、它是一款超轻量极或者说是微型的工作流引擎,而且绿色无污染,它只有一个dll,大小仅1M左右。 
2、它目前支持SQL Server、MySql、Oracle、SQLite、PostgreSql等多种数据库 
3、体型上来说它虽然是微型,但功能上并不算微型,它的设计结合了现代的OA及传统工作流、基本上可以实现我们大多数的功能需要。 
4、它其实是面向开发者设计的,从上面初始印象中的实例代码中大家可以看到,它的接口是很集中、精简、友好的,让开发者容易理解而且使用起来更方便简单。所以它更适合嵌入到项目中开发。 
缺点: 
1、它现在没有流程设计器、管理系统、表单设计器等,充其量只能算是一个类库,并不是直接拿来就可以使用。 
2、目前刚刚完成第一个内部版本,而且目前只在我们内部项目中使用,所以它不够成熟,虽然我们会持续的改进和完善。 
3、缺乏成功应用的案例。 
对于我们自己来说,这些缺点都是我们需要继续努力的地方,可能还需要大量的时间来完成。目前来说我们还不打算开源,等它慢慢稳定成熟后我们会考虑是不是开源出来。如果大家有好的建议或有哪方面的疑惑我很乐意给大家解答,或者你也在设计开发自己的工作流,我们可以相互交流下。

时间: 2024-10-13 12:02:00

微型工作流引擎设计的相关文章

我的微型工作流引擎设计

一.前言 提到工作流很多人就会想到OA,的确OA就是典型的工作流的应用,但是工作流并不仅仅局限于OA,工作流应该算是基础框架软件,主要用于流程的重组和优化,它有广阔的应用领域.在java下有很多优秀的开源工作流可以选择比如activit5.jpbm4等,在.net下却几乎找不到令人满意的工作流引擎可用.当然不是说.net下没有开源的只是有些国产开源的但看了代码后就一点兴趣都没有了,且不说代码质量如何,还引入了一大堆的东西,想在项目中应用也是非常困难.鉴于此我还是决定自己开发一款.NET微型工作流

微型工作流引擎-功能设计

我的微型工作流引擎-功能设计解析及使用示例 一.前言 上一篇我给大家介绍了我的工作流的模型和基本的设计,这篇我想详细说明下我这款工作流的功能及使用示例.这款工作流主要是面向开发者设计的,为了先让大家有个全局的认识,局部功能的设计实现就不细说了,后续有时间我会继续写文章向大家介绍. 二.功能详解及使用示例代码 1.配置流程引擎,一般在程序启动过程中调用(Global.asax.cs中) //初始化流程引擎 BpmConfiguration .Instance() .Config(@"C:\Conf

工作流引擎设计第一版

很久没写点东西了,现在有点时间来分享下工作流引擎设计的一点体会.希望能帮助各位园友. 前段时间接手一OA系统项目,经过一段时间的需求调研,总共十多个功能模块,但系统主要功能是应付一堆堆审批流程,各流程千差万别,而且流程变动也大,这无疑是需要设计一个工作流引擎才能解决.这个引擎主要做到流程可配置,可视化编辑,可视化的流程图展示,且需要保留审批处理的历史快照...... 经过一段时间的资料查阅(感谢园子的大虾们),并且经合自身的经历(曾经用过,但未曾开发过工作流引擎),终于想出了一套方案: 以下是相

我的微型工作流引擎-办公应用实战

一.前言 前面已经给大家介绍了我的工作流引擎的总体设计及的API设计,这篇是实战篇说说怎么实际应用了,这就得涉及到UI界面了.首先我们常用的工作流个人办公应用系统至少要包括发起流程.待办事项.已办事项等.我们设计了一个尽量简单的系统,能够满足个人办公的基本需求,只实现以下功能:     1.发起流程     2.待办事项     3.已办事项     4.我的流程     5.我的消息     6.我的委办 这些功能基本就是流程能正常的运行流转基础,其实只应用了我们引擎的一小部分功能,其它功能如

我的微型工作流引擎-功能设计解析及使用示例

一.前言 上一篇我给大家介绍了我的工作流的模型和基本的设计,这篇我想详细说明下我这款工作流的功能及使用示例.这款工作流主要是面向开发者设计的,为了先让大家有个全局的认识,局部功能的设计实现就不细说了,后续有时间我会继续写文章向大家介绍. 二.功能详解及使用示例代码 1.配置流程引擎,一般在程序启动过程中调用(Global.asax.cs中) //初始化流程引擎 BpmConfiguration .Instance() .Config(@"C:\Configration\BpmConfig.xml

驰骋工作流引擎设计系列02

流程实例的生成设计 第1节. 关键字 驰骋工作流引擎 流程快速开发平台 workflow ccflow jflow 第2节. 关于WorkID的设计 workid也叫流程实例id, 理解清楚workid的整个过程有助于理解如何获得数据,以及相关流程引擎表,业务数据表的产生变化的过程. 第3节. 概要说明 工作流程引擎的WorkID,也叫流程实例的ID,他是一个Int64类型的,自动增长的数据类型,经过严格的测算,一般应用不会枯竭. 一个workid可会贯穿整个流程的生命周期,从workid创建开

驰骋工作流引擎设计系列04 流程引擎表结构的设计

第1节. 关键字 驰骋工作流引擎 流程快速开发平台 workflow ccflow jflow 第1节. 流程引擎表结构的设计 流程引擎表是流程引擎控制流程运转的数据存储表,是整个流程引擎的核心表.理解表结构,掌握状态字段,相关字段变化的规律,就掌握的整个流程引擎运转的规律了. 1.1.1: 流程引擎表的作用 流程引擎表,是用来存储流程运行中信息的表. 流程在运行过程中,需要把中间数据写入到该表中. 一个流程启动后,就创建一个workid,就在流程引擎注册表里注册一条数据,有一个字段WFStat

驰骋工作流引擎设计系列06 保存草稿设计

第1节. 关键字 驰骋工作流引擎 流程快速开发平台 workflow ccflow jflow 第1节. ccflow保存与保存草稿设计 保存,就是用户点击保存所要执行的工作,在讲解这个概念之前,我们要了解什么是草稿规则. 1.1.1:ccflow 关于草稿规则 定义:流程发起工作做了一部分,就关闭了下次处理,对这件工作我们就称为草稿. 应用背景:草稿也是常用功能之一,它是针对于,开始节点的表单才有意义.它类似于我们的邮件草稿,当您发起一个工作后,录入了一些数据,有与其他的原因,需要暂停该工作,

驰骋工作流引擎设计系列10时效考核规则设计

第1节. 关键字 驰骋工作流引擎 流程快速开发平台 workflow ccflow jflow 第1节. 时效考核规则设计 考核是流程运行的副产品,业务搬到了计算机上,整个运行轨迹就会被有效的记录下来.CCBPM的考核分为时效考核.质量考核.时效考核是对工作及时程度的一种考核,而质量考核是一个节点对上一个节点工作完成好坏的一个考核. 1.1.1: 时效考核的系统配置 系统配置分为工作日信息设置,节假日信息设置. 上下班&午休时间配置,该设置在全局变量里:JFlow的配置: CCFlow的配置: