天天看點

嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程

子流程

描述
  • 子流程(Sub-process)是一個包含其他節點,網關,事件等等的節點
  • 本身就是一個流程,同時是更大流程的一部分.子流程是完全定義在父流程裡的,是以叫做内嵌子流程
  • 子流程的兩種主要場景:
    • 子流程可以使用繼承式模組化: 很多模組化工具的子流程可以折疊,把子流程的内部細節隐藏,顯示一個進階别的端對端的業務流程總覽
    • 子流程會建立一個新的事件作用域: 子流程運作過程中抛出的事件,可以被子流程邊緣定義的邊界事件捕獲,就可以建立一個僅限于這個子流程的事件作用範圍
  • 使用子流程的限制:
    • 子流程隻能包含一個空開始事件, 不能使用其他類型的開始事件,子路程必須至少有一個結束節點
    • 順序流不能跨越子流程的邊界
圖形标記
  • 子流程顯示為标準的節點(圓角矩形),下面子流程是折疊的,隻顯示名稱和一個加号标記,展示了進階别的流程總覽:
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程
  • 下面子流程是展開的,子流程的步驟都顯示在子流程邊界内:
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程
  • 使用子流程主要是為了定義對應事件的作用域
  • 示例:
    • 調查軟體/調查引薦任務需要同步執行,兩個任務需要在同時完成,在二線支援解決之前.這裡,定時器的作用域(比如節點需要及時完成)是由子流程限制的:
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程
XML内容
  • 子流程定義為subprocess元素.所有節點,網關,事件,等等.是子流程的一部分,都需要放在這個元素裡
<subProcess id="subProcess">

  <startEvent id="subProcessStart" />

  ... other Sub-Process elements ...

  <endEvent id="subProcessEnd" />

 </subProcess>           

事件子流程

  • 事件子流程是由事件觸發的子流程.是BPMN 2.0中的新元素
  • 事件子流程可以添加到流程級别或任意子流程級别
  • 用于觸發事件子流程的事件是使用開始事件配置的,是以事件子流程是不支援空開始事件的
  • 事件子流程可以被消息事件,錯誤事件,信号事件,定時器事件,或補償事件觸發.開始事件的訂閱在包含事件子流程的作用域(流程執行個體或子流程)建立時就會建立.當作用域銷毀也會删除訂閱。
  • 事件子流程可以是中斷的或非中斷的
    • 一個中斷的子流程會取消目前作用域内的所有流程
    • 非中斷事件子流程會建立一個新的同步分支
    • 中斷事件子流程隻會被每個激活狀态的宿主觸發一次
    • 非中斷事件子流程可以觸發多次
    • 子流程是否是中斷的,使用事件子流程的開始事件配置
  • 事件子流程不能有任何進入和外出流程
    • 當事件觸發一個事件子流程時,輸入順序流是沒有意義的
    • 當事件子流程結束時,無論目前作用域已經結束(中斷事件子流程的情況或為非中斷,子流程生成同步分支會結束
  • 事件子流程的限制:
    • Activiti隻支援中斷事件子流程
    • Activiti隻支援使用錯誤開始事件或消息開始事件的事件子流程
圖像标記
  • 事件子流程可以顯示為邊框為虛線的内嵌子流程
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程
  • 事件子流程的XML内容與内嵌子流程一樣,但是要把triggeredByEvent屬性設定為true
<subProcess id="eventSubProcess" triggeredByEvent="true">
        ...
</subProcess>           
執行個體
  • 使用錯誤開始事件觸發的事件子流程的執行個體,事件子流程是放在流程級别的,作用于流程執行個體
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程

事件子流程的XML:

<subProcess id="eventSubProcess" triggeredByEvent="true">
        <startEvent id="catchError">
                <errorEventDefinition errorRef="error" />
        </startEvent>
        <sequenceFlow id="flow2" sourceRef="catchError" targetRef="taskAfterErrorCatch" />
        <userTask id="taskAfterErrorCatch" name="Provide additional data" />
</subProcess>           

事件子流程也可以添加成内嵌子流程.如果添加為内嵌子流程,其實是邊界事件的一種替代方案

    • 下面兩個流程圖,兩種情況内嵌子流程會抛出一個錯誤事件,兩種情況錯誤都會被捕獲并使用一個使用者任務處理
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程

相對于

嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程
  • 兩種場景都會執行相同的任務,但是兩種模組化的方式是不同的:
    • 内嵌子流程是使用與執行作用域宿主相同的流程執行的:
      • 意思是内嵌子流程可以通路它作用域内的内部變量
      • 當使用邊界事件時,執行内嵌子流程的流程會删除, 并生成一個流程根據邊界事件的順序流繼續執行,這意味着内嵌子流程建立的變量不再起作用
    • 當使用事件子流程時,事件是完全由它添加的子流程處理的.
      • 當使用邊界事件時,事件由父流程處理
  • 這兩個不同點可以幫助決定是使用邊界事件(内嵌子流程)還是内嵌事件子流程(事件子流程) 來解決特定的流程模組化或者實作問題

事務子流程

  • 事務子流程是内嵌子流程, 可以用來把多個流程放到一個事務裡
  • 事務是一個邏輯單元, 可以把一些單獨的節點放在一起, 這樣它們就可以一起成功或一起失敗
  • 事務的可能結果有三種:
    • 事務成功,沒有取消也沒有因為問題終結
      • 如果事務子流程是成功的,就會使用外出順序流繼續執行
      • 如果流程後來抛出了一個補償事件,成功的事務可能被補償
      • 和普通内嵌子流程一樣,事務可能在成功後,使用中間補償事件進行補償
    • 事務取消,流程到達取消結束事件
      • 所有流程都會終結和删除,觸發補償的一個單獨的流程,會通過取消邊界事件繼續執行
      • 在補償完成之後,事務子流程會使用取消邊界事務的外出順序流向下執行
    • 事務被問題結束,抛出一個錯誤事件而且沒有在事務子流程中捕獲(如果錯誤被事務子流程的邊界事件處理了,也會這樣應用)
      • 不會執行補償
  • 事務三種不同的結果:
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程
  • BPMN事務與ACID(技術)事務的關系: BPMN事務子流程與技術(ACID)事務不能互相混淆,BPMN事務子流程不是技術(ACID)事務領域的
  • BPMN事務和技術事務有以下不同點:
    • ACID事務一般是短期的.BPMN事務可能持續幾小時,幾天,甚至幾個月才能完成:
      • 考慮事務中包含的節點可能有使用者任務,一般人員響應的時間比應用時間要長
      • 在其他情況下,bpmn事務可能要等待發生一些事務事件,例如要根據某種次序執行
      • 這種操作通常要相比更新資料庫的一條資料,或把一條資訊儲存到事務性隊列中,消耗更長的時間來完成
    • BPMN事務一般要跨越多個ACID事務,因為不能在整個業務節點的過程中保持一個技術性的事務
    • BPMN事務會跨越多個ACID事務,是以會喪失ACID的特性:
      • 比如,在上述例子中,假設預訂旅店和刷信用卡操作在單獨的ACID事務中執行,假設預定旅店節點已經成功了
      • 現在處于一個中間不穩定狀态,因為我們預定了酒店,但是還沒有刷信用卡
      • 在一個ACID事務中,要依次執行不同的操作,也會有一個中間不穩定狀态
      • 不同的是,這個中間狀态對事務的外部是可見的.比如,如果通過外部預定服務進行了預定,其他使用相同預定服務的部分就可以看到旅店被預定了.這意味着實作業務事務時,我們完全失去了隔離屬性(放棄隔離性,可以為ACID事務獲得更高的并發,是可以完全控制,中間不穩定狀态也隻持續很短的時間)
    • BPMN業務事務也不能使用通常的方式復原:
      • BPMN事務跨越了多個事務,BPMN事務取消時一些ACID事務可能已經送出了.這時不能被復原
  • BPMN事務運作時間很長,缺乏隔離性和復原機制都需要被差別對待:
    • 使用補償執行復原:
      • 如果事務範圍抛出了取消事件,會影響已經執行成功的節點,并使用補償處理器執行補償
    • 隔離性的缺乏通常使用特定領域的解決方法來解決:
      • 在上面的例子中,一個旅店房間可能會展示給第二個客戶,在我們确認第一個客戶付費之前.雖然這可能與業務預期不符,預定服務可能選擇允許一些過度的預約
    • 事務會因為風險而中斷,服務必須處理這種情況:
      • 已經預定了旅店,但是一直沒有付款的情況(因為事務被中斷了),這時預定服務需要選擇一個政策,在旅店房間預定超過最大允許時間後,如果還沒有付款,預定就會取消
  • 綜上所述,ACID處理的是通常問題:復原,隔離級别和啟發式結果,在實作業務事務時,需要找到特定領域的解決方案來處理這些問題
  • BPMN事務目前的限制:
    • BPMN規範要求流程引擎能根據底層事務的協定處理事件:
      • 比如如果底層協定觸發了取消事件,事務就會取消
  • ACID事務頂層的一緻性和優化并發:
    • BPMN事務保證一緻性:
      • 要麼所有節點都成功
      • 一些節點成功,對其他成功的節點進行補償
      • 無論哪種方式,都會有一緻性的結果
      • 要讨論一些activiti内部的情況BPMN事務的一緻性模型是疊加在流程的一緻性模型之上的
    • Activiti執行流程是事務性的,并發使用了樂觀鎖.在Activiti中,BPMN錯誤,取消和補償事件都建立在同樣的ACID事務與樂觀鎖之上:
      • 取消結束事件隻能觸發它實際到達的補償
      • 如果之前服務任務抛出了未聲明的異常
      • 補償處理器的效果無法送出,如果底層的acid事務的參與者把事務設定成必須復原.
      • 當兩個并發流程到達了取消結束事件
      • 可能會觸發兩次補償,并因為樂觀鎖異常失敗
      • 說明Activiti中實作BPMN事務時,相同的規則也作用域普通的流程和子流程
      • 為了保證一緻性,重要的是使用一種方式考慮實作樂觀事務性的執行模型
  • 事務子流程顯示為内嵌子流程, 使用雙線邊框
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程
  • 事務子流程使用transaction标簽
<transaction id="myTransaction" >
        ...
</transaction>           
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程

調用活動(子流程)

  • BPMN 2.0區分了普通子流程(内嵌子流程)和調用節點:
    • 相同點: 當流程抵達節點時兩者都會調用子流程
    • 不同點:
      • 調用節點引用流程定義外部的一個流程
      • 子流程會内嵌到原始的流程定義中
      • 使用調用節點的主要場景: 需要重用流程定義,這個流程定義需要被很多其他流程定義調用
  • 當流程執行到調用節點,會建立一個新分支,是到達調用節點的流程的分支
  • 這個分支會用來執行子流程,預設建立并行子流程,就像一個普通的流程
  • 上級流程會等待子流程完成,然後才會繼續向下執行
  • 調用節點顯示與子流程相同,但是粗邊框(無論是折疊和展開的). 根據不同的模組化工具,調用節點也可以展開,但是顯示為折疊的子流程
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程
<callActivity id="callCheckCreditProcess" name="Check credit" calledElement="checkCreditProcess" />           
  • 子流程的流程定義是在執行階段解析的,就是說子流程可以與調用的流程分開部署
傳遞變量
  • 可以把流程變量傳遞給子流程,反之亦然: 當它啟動的時候, 資料會複制給子流程,并在它結束的時候複制回主流程
<callActivity id="callSubProcess" calledElement="checkCreditProcess" >
  <extensionElements>
          <activiti:in source="someVariableInMainProcess" target="nameOfVariableInSubProcess" />
          <activiti:out source="someVariableInSubProcss" target="nameOfVariableInMainProcess" />
  </extensionElements>
</callActivity>           

這裡使用Activiti擴充來簡化BPMN标準元素調用dataInputAssociation和 dataOutputAssociation, 隻在使用BPMN 2.0标準方式聲明流程變量有效

  • 也可以使用表達式:
<callActivity id="callSubProcess" calledElement="checkCreditProcess" >
        <extensionElements>
          <activiti:in sourceExpression="${x+5}"" target="y" />
          <activiti:out source="${y+5}" target="z" />
        </extensionElements>
</callActivity>           
z = y + 5 = x + 5 + 5           
  • 訂單處理流程圖:先判斷用戶端信用,檢查信用階段設計成調用節點
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程
  • 流程XML:
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="receiveOrder" />

<manualTask id="receiveOrder" name="Receive Order" />
<sequenceFlow id="flow2" sourceRef="receiveOrder" targetRef="callCheckCreditProcess" />

<callActivity id="callCheckCreditProcess" name="Check credit" calledElement="checkCreditProcess" />
<sequenceFlow id="flow3" sourceRef="callCheckCreditProcess" targetRef="prepareAndShipTask" />

<userTask id="prepareAndShipTask" name="Prepare and Ship" />
<sequenceFlow id="flow4" sourceRef="prepareAndShipTask" targetRef="end" />

<endEvent id="end" />           
  • 子流程:
嵌入式工作流程開發!工作流 Activiti 架構中子流程的使用指南子流程