個人微型工做流引擎設計

1、前言

    提到工做流不少人就會想到OA,的確OA就是典型的工做流的應用,可是工做流並不只僅侷限於OA,工做流應該算是基礎框架軟件,主要用於流程的重組和優化,它有廣闊的應用領域。在java下有不少優秀的開源工做流能夠選擇好比activit五、jpbm4等,在.net下卻幾乎找不到使人滿意的工做流引擎可用。固然不是說.net下沒有開源的只是有些國產開源的但看了代碼後就一點興趣都沒有了,且不說代碼質量如何,還引入了一大堆的東西,想在項目中應用也是很是困難。鑑於此我仍是決定本身開發一款.NET微型工做流引擎。java

2、基本說明

    爲何叫微型工做流引擎?就是超輕量級,以方便在項目中輕便的使用,好比只有一個類庫dll,大小也就幾百k到1M左右,不過咱們要先回過頭來看看工做流系統,它實在是太大了,它應該包括:
    一、工做流引擎
    二、工做流設計器
    三、工做流管理系統
    四、表單設計器node

       目前來講的我只實現了核心引擎,流程定義也只能先在xml中編輯而後讀取到引擎中或者直接定義到數據庫中,但整個流程是可以正常流轉。至於流程設計器、表單設計器、工做流管理系統這個我有精力了再慢慢開發。這裏我完成的只是很小的一塊,可是是工做流的核心,能夠很方便的嵌入到業務系統中應用。web

    引擎主要提供了對於工做流定義的解析以及流程流轉的支持。工做流定義文件描述了業務的交互邏輯,工做流引擎經過解析工做流定義文件按照業務的交互邏輯進行業務的流轉,工做流引擎一般經過參考某種模型來進行設計,經過調度算法來進行流程的流轉(流程的啓動、終止、掛起、恢復等),經過各類環節調度算法來實現對於環節的流轉(環節的合併、分叉、選擇、條件性的選擇等)。算法

3、初步印象

    一、從概念開始解釋估計你們都會看不下去了。咱們先拿一個簡單實例來看看,新建一個項目,引用個人工做流引擎類庫(Chitu.Bpm.dll,取名爲赤兔)。
在項目啓動時配置流程引擎(Global.asax.cs中),以下:    sql

//初始化流程引擎
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(); //發佈流程

啓動流程:express

//啓動流程
var process = bpm.NewProcessIntance("請假流程ID", "蕭秦(業務ID)");   //建立流程實例
process.SetVariable("流程變量1", "值1");                     //設置流程變量
process.Start();

人工任務節點轉交下一步:c#

//任務完成
var task = bpm.LoadTaskInstance("任務ID");
task.SetVariable("任務變量2", "xx");
task.Signal(); //觸發令牌流轉

全部的操做都經過Facade模式集中到BpmContext中,操做簡單方便。框架

二、接下來咱們先看看流程定義的XML,如下是我捏造的一個流程,以便把各類節點都放進去了。async

<?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包括幾種類型:一、class 二、script 三、sql 四、webservice 五、expression
在script或expression中能夠直接訪問process.xxx屬性或task.xxx屬性或variable.xxx簡化了動態c#語句的使用。
固然XML定義中還有不少其它的屬性定義我這裏也沒有都列出來,之後用到了再仔細說。

三、關於數據庫設計,這裏僅僅是流程流轉核心所須要的表,表之間都沒有拉關係
image

  4、部分功能剖析

    a、我把它劃分爲主要的幾大模塊: 引擎配置、流程定義、實例流轉、日誌處理、計劃任務
        引擎配置:配置引擎實例的數據庫鏈接、日誌配置、參數設定等。
        流程定義:利用xml來描述流程,主要定義任務節點,路由、動做事件、變量、人員分配等
        實例流轉:根據定義運行流程實例
        日誌處理:輸出日誌
        任務計劃:會啓動一個服務,用於處理好比延時啓動,任務過時等

    b、流轉中的關鍵性類設計包括:
        一、流程對象(Process)
        二、工做任務(Task)
        三、路由(Trasition)
        四、令牌(Token)
        五、事件總線與動做處理 (EventBus、ActionHandler)
        六、人員分配及委託機制(Assignment、Depute)
        七、流程回退處理(RollbackService)
        八、消息服務(NotifyService)

     c、一般引擎控制流程調度流轉核心的調度算法主要有FSM以及PetriNet兩種,基於調度算法來完成流程的流轉:
        一、FSM(有限狀態機)
        FSM 的定義爲包含一組狀態集(states)、一個起始狀態(start state)、一組輸入符號集(alphabet)、一個映射輸入符號和當前狀態到下一狀態的轉換函數(transition function)的計算模型。當輸入符號串,模型隨即進入起始狀態。它要改變到新的狀態,依賴於轉換函數。在有限狀態機中,會有有許多變量,例如,狀態機有不少與動做(actions)轉換(Mealy機)或狀態(摩爾機)關聯的動做,多重起始狀態,基於沒有輸入符號的轉換,或者指定符號和狀態(非定有限狀態機)的多個轉換,指派給接收狀態(識別者)的一個或多個狀態,等等。遵循FSM流程引擎經過狀態的切換來完成流程的流轉。
        二、PetriNet
        信息流的一個抽象的、形式的模型。指出一系統的靜態和動態性質。PetriNet一般表示成圖。遵循PetriNet流程引擎經過令牌來決定流程的流轉。
        我採用的是第二種PetriNet算法。用Token來表示當前實例運行的位置,也利用token在流程各個點之間的轉移來表示流程的推動,以下圖所示:
   image001  
      令牌流轉邏輯,我把如下類方法都作一個簡化省略了路由選擇及節點處理細節,好讓你們明白令牌的流轉:

//令牌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三、參與者組織模型接口

5、總結

目前個人這款工做流引擎還在繼續完善當中,我總結下它的優缺點: 優勢: 一、它是一款超輕量極或者說是微型的工做流引擎,並且綠色無污染,它只有一個dll,大小僅1M左右。 二、它目前支持SQL Server、MySql、Oracle、SQLite、PostgreSql等多種數據庫 三、體型上來講它雖然是微型,但功能上並不算微型,它的設計結合了現代的OA及傳統工做流、基本上能夠實現咱們大多數的功能須要。 四、它實際上是面向開發者設計的,從上面初始印象中的實例代碼中你們能夠看到,它的接口是很集中、精簡、友好的,讓開發者容易理解並且使用起來更方便簡單。因此它更適合嵌入到項目中開發。 缺點: 一、它如今沒有流程設計器、管理系統、表單設計器等,充其量只能算是一個類庫,並非直接拿來就可使用。 二、目前剛剛完成第一個內部版本,並且目前只在咱們內部項目中使用,因此它不夠成熟,雖然咱們會持續的改進和完善。 三、缺少成功應用的案例。 對於咱們本身來講,這些缺點都是咱們須要繼續努力的地方,可能還須要大量的時間來完成。目前來講咱們還不打算開源,等它慢慢穩定成熟後咱們會考慮是否是開源出來。若是你們有好的建議或有哪方面的疑惑我很樂意給你們解答,或者你也在設計開發本身的工做流,咱們能夠相互交流下。聯繫13606021792

相關文章
相關標籤/搜索