工作流模式-工作流異常處理模式

版權聲明:工作流模式版權歸 Workflow Patterns 組 織 ( http://www.workflowpatterns.com ) 所 有 。 經 Workflow Patterns授權,中文簡體版由辛鵬和榮浩翻譯。未經譯者書面許可,不得將該中文簡體版用於商業目的。

在軟件開發裏,我們將不在自己控制範圍內因素所造成的問題和沒有預料到的情況稱爲異 常。工作流異常和軟件開發裏異常的概念一致,將流程實例執行過程中出現的問題和錯誤稱爲異 常,這些異常是由各種不確定因素造成的,從而使流程實例執行偏離了流程設計者最初的期望。 引起工作流異常的因素有很多,流程定義描述的不準確或不完整,執行環境的變化,不能獲取資 源等都會引起流程執行偏離預期。這些因素涉及系統異常:硬件、軟件、通訊、工作流模型、相 關應用程序、流程邏輯約束、工作流相關數據約束、時間約束以及執行算法;涉及業務異常:工 作人員請假離職、資源緊張、突發事件、用戶中止合同、項目目標發生變化等。

在Java和C++裏,當程序運行過程中出現異常時,會中止當前程序的運行,並將異常層層拋 出。工作流系統的異常處理與之相同,如果在當前的運行上下文裏,我們得不到足夠的信息來處 理這個問題,我們就會停止運行,並將這個問題交給上層進行處理,上層擁有更多的信息。在軟 件開發裏,異常處理的一個原則是:如果不知道該如何處理這個異常,那麼就別去捕捉它。這個 原則同樣適用於流程實例的執行過程,如果不知道如何處理一個問題,那麼就不要處理,把它留 給能處理這個問題的人去處理。

程序裏,異常處理的目標在於讓我們能用比現在更少的代碼,以一種更簡單的方式來開發大 型、可靠的程序。通過將處理異常的代碼從異常發生的地方移開,我們能夠在一個地方集中精力 去解決想解決的問題,然後再到另一個地方集中處理這些異常問題。程序的主線不會被異常處理 這類枝節問題給搞得支離破碎,程序也更易於理解和維護。這一目標同樣也是工作流系統異常處 理的目標,當應用工作流系統時,我們首先會進行流程建模,複雜的流程定義會導致流程的不可 管理,作爲一個原則,流程定義必須能夠被執行工作的人所理解。當對實際業務流程進行建模時, 如果只建模流程執行的樂觀路徑,模型會直接易懂,但如果將流程執行過程中的各種異常情況和如何處理都進行建模,那麼肯定會帶來巨大的複雜性,使得流程定義非常難以維護。此時一是需 要工作流系統提供異常處理機制;二是需要應用人員進行適當的異常分類與建模,並在合適的位 置設置異常處理器。

在前面的章節裏,我們分別討論了工作流的控制模式、資源模式和數據模式,這三種模式分 別對工作流的不同方面進行了描述,異常處理模式與這些模式都緊密關聯,因爲在工作流的執行 中,流程定義、流轉、資源分配與數據約束都會引起異常。

在本章裏,我們首先對工作流執行過程中可能出現的異常進行分類,一般來說,異常都會與 一個正在執行的工作項關聯,即當前正在執行的工作產生了異常,但外部環境的變化也會影響到 當前正在執行的工作。接下來我們將討論在不同的層次上對異常進行處理,這些層次包括工作項 級別和流程實例級別(包括了流程定義級別),以及異常發生時我們可以採取的恢復動作。當討 論完這些點之後,我們將會看到它們如何互相結合構成我們的工作流異常處理模式即面。

異常分類

流程執行過程中的異常分爲五類,如圖D-1所示。

圖D-1 工作流異常分類

  1. 工作項執行失敗:工作項所代表的工作不能繼續執行或無法按照期望完成。導致工作項 執行失敗的原因有很多種,與該工作項相關的硬件故障、軟件故障或網絡故障都會導致 活動參與者無法正常執行該工作項,同時活動參與者也可能會自己中止該工作項的執行 或者直接放棄。
  2. 超時:工作項未在指定的時間點完成或未在指定的時間點開始執行。
  3. 資源不可用:沒有可用的資源執行或完成工作項。有兩種情況,一是分配工作項時系統 找不到滿足執行該工作條件的資源(人手不夠,資源被佔用),二是工作項執行過程中,
    先前指定的資源不能繼續或無法執行該工作項(生病、離職、調動)。
  4. 外部觸發:外部觸發通常表現爲事件,組織外部的事件影響正在執行中的工作項。例如 用戶突然取消訂單會導致訂單處理流程中所有工作項的中止,並伴隨着業務回滾(收回 發貨)。
  5. 違反約束:工作流約束包括流程流轉的約束(流程死鎖,不能繼續執行,進入死循環)、 數據的約束、資源的約束(超出當前組織資源所能達到的能力)以及業務約束。工作流 系統運行過程中需要保證流程執行的合理性和一致性,需要對流程執行狀態進行持續的 監控。

工作項級別的異常處理

一般來說,異常都會與一個正在執行的工作項關聯,即當前正在執行的工作產生了異常,外部觸發是個例外,此時異常並不由流程自身執行產生,但是影響到當前正在執行的工作項。當發 生異常時,工作項級別有很多種可能的處理方式,這些方式與當前工作項狀態息息相關,所以在 討論具體的處理方式之前,我們先簡單回顧一下工作項的生命週期,然後討論工作項在其生命周 期的不同狀態時可以選擇的異常處理方式。

從資源的角度,工作項的生命週期具有6個狀態(相比資源模式裏的討論,進行了簡化),分 別是:提供給資源拾取(Offered)、指派給一個資源執行(Allocated)、執行(Started)、完成(Completed)、失敗(Failed)和撤回(Withdrawn)。如圖D-2所示。

圖D-2 工作項的生命週期

最開始,工作流系統創建工作項並將其提供給資源拾取,這裏的資源可以是單個資源也可以 是多個資源,工作項此時處於提供給資源拾取狀態。接下來,其中一個資源向工作流系統發送一個要求指派的請求,要求系統將該工作項指派給他進行執行,然後系統就會將工作項指派給該資 源執行,工作項此時處於指派給一個資源執行的狀態,同時,對於前一步工作項被提供的其他資 源來說,工作項被撤回了。接下來,資源向系統發送開始執行的請求,工作項即進入執行狀態。

最後,如果資源正常完成活動,會給系統發送請求,告訴活動完成,系統將工作項的狀態置爲完 成,工作項的生命週期即到此結束;而如果資源沒有按照期望完成活動或無法完成活動,工作項 的狀態置爲失敗,工作項的生命週期結束。

當工作項處於提供給資源拾取的被拾取狀態時,可能的異常處理方式包括以下4種。

  1. 繼續被拾取(OCO,continue-offer):工作項繼續保持被拾取的狀態,不發生任何變化。
  2. 重新分配資源拾取(ORO,re-offer):工作項重新分配給新的資源進行拾取。
  3. 強制完成(OFC,force-complete):工作項從資源的待拾取列表撤回,狀態變爲完成,觸發後續活動產生新的工作項。
  4. 強制失敗(OFF,force-fail):工作項從資源的待拾取列表撤回,狀態變爲失敗,不觸發後續活動。

圖D-3 工作項處於被拾取狀態的異常處理

當工作項處於指派給一個資源執行的被指派狀態時,可能的異常處理方式包括以下5種。

  1. 繼續被指派(ACA,continue-allocation):工作項繼續保持被指派的狀態,不發生任何變化。
  2. 重新指派(ARA,re-allocation):工作項從資源的待辦列表撤回,工作項重新分配給新的 10資源執行。
  3. 重新分配資源拾取(ARO,re-offer):工作項從資源的待辦列表撤回,工作項重新分配給新的資源進行拾取。
  4. 強制完成(AFC,force-complete):工作項從資源的待辦列表撤回,狀態變爲完成,觸發 後續活動產生新的工作項。
  5. 強制失敗(AFF,force-fail):工作項從資源的待辦列表撤回,狀態變爲失敗,不觸發後 續活動。

圖D-4 工作項處於被指派狀態的異常處理

當工作項處於執行狀態時,可能的異常處理方式包括以下6種。

圖D-5 工作項處於執行狀態的異常處理

  1. 繼續執行(SCE,continue-execution):工作項繼續保持執行的狀態,不發生任何變化。
  2. 重新開始執行(SRS,re-start):當前正在執行的工作中止,由同一個資源重新執行該工作項。
  3. 重新指派(SRA,re-allocation):當前正在執行的工作中止,工作項從資源的辦理列表撤回,工作項重新分配給新的資源執行。
  4. 重新分配資源拾取(SRO,re-offer):當前正在執行的工作中止,工作項從資源的辦理列表撤回,工作項重新分配給新的資源進行拾取。
  5. 強制完成(SFC,force-complete):當前正在執行的工作中止,工作項從資源的辦理列表撤回,狀態變爲完成,觸發後續活動產生新的工作項。
  6. 強制失敗(SFF,force-fail):當前正在執行的工作中止,工作項從資源的辦理列表撤回,狀態變爲失敗,不觸發後續活動。

流程實例級別的異常處理

異常不僅會影響到與其關聯的工作,往往還會影響到同一個流程實例里正在執行的其他工作 甚至同一個流程定義裏其他正在執行的工作,所以我們還需要在更高的一個級別進行處理。

可能的異常處理方式包括以下3種。

  1. 繼續執行(CWC,continue with case):當前流程實例中其他工作不受影響,流程實例繼續執行。異常在工作項級別已經得到完全的處理。
  2. 當前流程實例中止執行(RCC,remove current case):當前流程實例中的部分或所有工作中止執行,如果所有工作都中止執行,那麼即流程實例中止執行。異常所影響的範圍限於當前流程實例內。
  3. 所有屬於同一流程定義的流程實例都中止執行(RAC,remove all cases):屬於同一流程定義的流程實例中的部分或所有工作中止執行,如果所有工作都中止執行,那麼即所有 流程實例都中止執行。異常影響所有屬於同一流程定義的流程實例。

恢復動作

當異常發生時,執行過的工作已經產生了一定的影響,爲了使流程實例能夠繼續執行或正常 停止,必須對已執行工作所產生的影響進行消除,這是通過恢復動作完成的,該動作對流程中可 補償的工作進行補償。

可能的恢復動作包括以下3種。

  1. 什麼都不做(NIL,no action):什麼都不做。
  2. 回滾(RBK,rollback):流程實例狀態重置至異常發生前的一個回滾點。
  3. 補償(COM,compensate):額外的補償動作,消除異常所產生的影響。

對於回滾,我們需要記錄一個回滾點,通過執行日誌記錄流程實例執行過程中的事件,當回滾動作發生時,我們將執行日誌中回滾點後續的執行事件全部撤銷。我們並不需要將流程實例回 滾後的狀態與流程實例當時位於回滾點的狀態完全一致,我們需要的只是消除異常所產生的影 響,所以執行日誌不需要詳細記錄流程實例中的每一個執行事件。同時,有一些操作也是回滾動 作無法恢復的,例如資源浪費的時間、已經發送的文檔/報告等。

補償動作相對回滾來說有很多的靈活性,我們不僅可以將發生過的事件撤回,還可以額外進 行一些操作(例如通過異常路徑繼續執行流程實例),來消除異常所帶來的影響。

圖D-6 BPMN裏的異常流屬於補償動作

異常處理模式

對每一種的異常而言,都可能存在不同的處理方式,我們把每種針對特定異常類型可能的處 理方式稱爲異常處理模式。一個異常處理模式包括4方面的內容:

  1. 異常的類型;
  2. 發生異常的活動如何處理即工作項級別對異常的處理;
  3. 發生異常的流程實例以及關聯流程實例如何處理即流程實例級別對異常的處理; 1. 採取何種恢復動作。

共有135種可能的異常處理模式。

工作執行失敗

  1. OFF-CWC-NIL
  2. OFF-CWC-COM
  3. OFC-CWC-NIL
  4. OFC-CWC-COM
  5. AFF-CWC-NIL
  6. AFF-CWC-COM
  7. AFC-CWC-NIL
  8. AFC-CWC-COM
  9. SRS-CWS-NIL
  10. SRS-CWC-COM
  11. SRS-CWC-RBK
  12. SFF-CWC-NIL
  13. SFF-CWC-COM
  14. SFF-CWC-RBK
  15. SFF-RCC-NIL
  16. SFF-RCC-COM
  17. SFF-RCC-RBK
  18. SFC-CWC-NIL
  19. SFC-CWC-COM
  20. SFC-CWC-RBK

工作超時

  1. OCO-CWC-NIL
  2. ORO-CWC-NIL
  3. OFF-CWC-NIL
  4. OFF-RCC-NIL
  5. OFC-CWC-NIL
  6. ACA-CWC-NIL
  7. ARA-CWC-NIL
  8. ARO-CWC-NIL
  9. AFF-CWC-NIL
  10. AFF-RCC-NIL
  11. AFC-CWC-NIL
  12. SCE-CWC-NIL
  13. SCE-CWC-COM
  14. SRS-CWC-NIL
  15. SRS-CWC-COM
  16. SRS-CWC-RBK
  17. SRA-CWC-NIL
  18. SRA-CWC-COM
  19. SRA-CWC-RBK
  20. SRO-CWC-NIL
  21. SRO-CWC-COM
  22. SRO-CWC-RBK
  23. SFF-CWC-NIL
  24. SFF-CWC-COM
  25. SFF-CWG-RBK
  26. SFF-RCC-NIL
  27. SFF-RCC-COM
  28. SFF-RCC-RBK
  29. SFC-CWC-NIL
  30. SFC-CWC-COM

資源不可用

  1. ORO-CWC-NIL
  2. OFF-CWC-NIL
  3. OFF-RCC-NIL
  4. OFC-CWC-NIL
  5. ARO-CWC-NIL
  6. ARA-CWC-NIL
  7. AFF-CWC-NIL
  8. AFF-RCC-N1L
  9. AFC-CWC-NIL
  10. SRA-CWC-NIL
  11. SRA-CWC-COM
  12. SRA-CWC-RBK
  13. SRO-CWC-NIL
  14. SRO-CWC-COM
  15. SRO-CWC-RBK
  16. SFF-CWC-NIL
  17. SFF-CWC-COM
  18. SFF-CWC-RBK
  19. SFF-BCC-NIL
  20. SFF-BCC-COM
  21. SFF-RCC-RBK
  22. SFF-RAC-NIL
  23. SFC-CWC-NIL
  24. SFC-CWC-COM

外部觸發

  1. OCO-CWC-NIL
  2. OFF-CWC-NIL
  3. OFF-RCC-NIL
  4. OFC-CWC-NIL
  5. ACA-CWC-NIL
  6. AFF-CWC-NIL
  7. AFF-RCC-NIL
  8. AFC-CWC-NIL
  9. SCE-CWC-NIL
  10. SRS-CWC-NIL
  11. SRS-CWC-COM
  12. SRS-CWC-RBK
  13. SFF-CWC-NIL
  14. SFF-CWC-COM
  15. SFF-CWC-RBK
  16. SFF-RCC-NIL
  17. SFF-RCC-COM
  18. SFF-RCC-RBK
  19. SFF-RAC-NIL
  20. SFC-CWC-NIL
  21. SFC-CWC-COM

違反約束

  1. SCE-CWC-NIL
  2. SRS-CWC-NIL
  3. SRS-CWC-COM
  4. SRS-CWC-RBK
  5. SFF-CWC-NIL
  6. SFF-CWC-COM
  7. SFF-CWC-RBK
  8. SFF-RCC-NIL
  9. SFF-RCC-COM
  10. SFF-RCC-RBK
  11. SFF-RAC-NIL
  12. SFC-CWC-NIL
  13. SFC-CWC-COM

其他的異常分類和處理

Bruce Silver 的異常處理模式

Bruce Silver(http://brsilver.com/)的異常處理基於BPMN,關注如何建模以顯式的捕獲異常, 異常通過異常路徑進行處理。這種定義存在的侷限:異常處理過於單一,例如,很多時候我們並 不需要定義異常路徑,我們需要做得僅僅是暫停流程實例並通知流程實例負責人;並未涉及異常 處理的細節,例如,對工作項的各種可能異常處理都沒有涉及;所捕獲的異常屬於可預知的異常(所以可以進行建模),對不可預知異常沒有涉及。

Bruce Silver根據異常產生的原因進行了分類,如圖D-7所示。

  1. 業務異常:工作項能夠執行完成,但是返回異常的結果(排除系統異常)。根據異常產生 的原因又分爲組織內部原因觸發和組織外部原因觸發。內部觸發包括了活動參與者做出 的非期望行爲(取消活動)、超時、業務規則約束(資源不可用),外部觸發包括了用戶 突然取消或改變決定。
  2. 系統異常:與工作項相關的硬件故障、軟件故障或網絡故障所導致的工作項無法執行。例如工作項調用的Web服務連接超時、調用失敗。

圖D-7 根據原因所進行的異常分類

Bruce Silver將異常處理模式分爲了7種:內部業務異常處理、重新拋出異常處理、活動超時處理、系統異常處理、非請求的外部異常處理、請求等待響應的外部異常處理和事務。

內部業務異常處理

組織內部原因導致的業務異常,包括活動參與者做出的非期望行爲和違反業務規則約束,例 如活動參與者對訂單審批不通過、業務數據不完整、送貨前發現缺貨。此時使用網關進行建模, 不使用異常事件。

圖D-8 內部業務異常處理

重新拋出異常處理

下層流程無法完全處理的異常繼續拋出,上層流程繼續處理。

圖D-9 拋出/捕獲異常

活動超時處理

活動處理超時。

圖D-10 活動超時處理

系統異常處理

調用的Web服務連接超時、調用失敗,與人無關。

圖D-11 系統異常處理

非請求的外部異常處理

非請求的外部觸發意味着流程實例執行過程並未向外部請求響應,事件是由外部驅動觸發 的。使用消息事件捕獲外部觸發,將外部觸發可能影響的活動建模爲塊活動或者子流程(建立起 上下文),忽略過早或過晚的外部觸發。

圖D-12 BPMN建模的外部觸發異常處理

請求等待響應的外部異常處理

請求等待響應意味着流程實例執行過程中需要與外部交互,向外部發送請求並等待外部的響 應。使用事件網關進行建模。

圖D-13 請求外部響應異常處理

事務

事務由事務協議所支持,如 WS-Transaction。

Ziv Ben-Eliahu 和 Michael Elhadad 的語義流程建模

Ziv Ben-Eliahu和Michael Elhadad的論文(http://www.cs.bgu.ac.il/~bpmn/wiki.files/Paper.pdf) 從Java的Checked異常獲取靈感,擴展了BPMN的活動,給活動增加了3種元數據:語義屬性、異 常和異常處理器。異常定義活動運行期可能產生的異常(異常事件),異常處理器定義活動對應 的異常處理器,語義屬性對活動進行語義描述。

實際應用時,業務人員快速對樂觀路徑進行建模,定義活動時輸入可能產生的異常然後迅速 跳過。稍後,建模工具對活動定義進行檢查(類似於Java裏的編譯檢查),如果找不出活動異常 對應的處理器,那麼報錯,強制業務分析人員返回來繼續異常處理的建模。如果業務分析人員沒 有輸入異常,那麼建模工具會根據活動具有業務語義的關鍵詞或活動定義本身推斷出活動運行期 可能出現的異常,依據推斷異常進行檢查。例如,一個通知顧客的活動,語義關鍵詞是通知,那 麼工具推斷出通知包括了3步:發送數據、接受返回數據和對返回數據進行處理,那麼可能的異常就包括:發送數據失敗、返回數據超時和返回數據非法。基於活動語義的異常推斷需要我們建 立起相應的語義倉庫,實現關鍵詞的檢索和推斷。

Ziv Ben-Eliahu和Michael Elhadad強制業務分析人員對異常進行建模處理的原因在於:他們認 爲對於複雜流程來說,業務分析人員往往關注於樂觀路徑而忘記對異常進行處理;存在不熟悉業 務的建模人員,這些人需要從語義推斷中獲得建議。

我們認爲作者還有一層考慮,即認爲捕獲異常的最佳時機是在建模的時候,也就是在流程執 行之前,這和Java的基本哲學一致:糟糕的代碼根本就得不到執行。

但Ziv Ben-Eliahu和Michael Elhadad的異常處理忽略了兩種情況:一是對所有異常都建模處理 會增加流程模型的複雜性,這違反了異常處理的目標:保持流程模型的簡單、所有執行者都可理 解;二是作爲一個通用的實踐:大部分流程執行過程中的異常處理都是脫離於工作流系統之外的, 是由人來處理的,工作流系統只是通知。工具只是工具。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章