2019 年初我在重新設計我們組負責的流程系統時,選擇了 Camunda 流程引擎,並基於該流程引擎實現了一套適配方案。以前就想做一次總結,但總拖着。
最近公司中台在做流程引擎選型,相關同事找我了解 Camunda 以及基於 Camunda 的應用方案。經過我一番說明,對方表示收獲很大。我想着也是時候把這些經驗寫下來了。
我把內容分為兩部分:
- Camunda 自身的介紹(為什么選 Camunda ?)
- 基於 Camunda 的一種適配層實現方案
這一篇只包括第一部分的內容。
為什么選 Camunda ?
做選型的時候,需要說明我們需要什么樣的功能和不需要什么樣的功能。
我們項目的特點是什么?
- 流程以自動化為主
極少數節點需要人工操作(審批、補充信息) - 使用 PHP 作為業務層語言
流程引擎必須作為一個服務存在,不能為了使用流程引擎而更改語言。
必須有一個機制,使得流程實例執行自動化操作時,請求業務層 API。 - 流程同一時間最多只有一個節點在執行
不需要支持並行加簽、多分支同時執行、單節點多並發執行。 - 可以強行跳轉到其他節點執行
由於業務的不確定性因素,難以或無法通過優化流程來預先規划好各種情況下的分支。
因此需要在自動化步驟出現某些無法預知的情況時,由運維修改流程實例的狀態,跳過當前節點的執行或者回到前面的節點重新執行。 - 可以重啟一個處於結束或終止狀態的流程實例
同樣是業務的要求。 - 支持多分支
有些流程引擎只能選擇 “是” 或者 “否” 這兩個分支,無法支持多種情況。 - 支持失敗重試
當自動化任務節點失敗后,流程引擎需要支持重試當前節點。
接下來了解比較常見的流程引擎。例如 JBPM 、 Activiti 、 Flowable 、 Camunda 、 Zeebe 。
更多流程引擎請見:
它們之間的關系是:
2004 2006 2009 2010 2013 2015 2017 2018 2020
+----------------------------------------------------------------------------------------> JBPM
2 3 4 5 6 7 7.15 7.34
+ 推 翻 架 構
| 繼 承
| 架 構
| 2010 2013 2015 2017 2018 2020
+-----------------------------------------------------------------------> Activiti
5 6 7 7.1
+ +
| |
| |
fork | fork | 2018 2020
| +------------------------------> Flowable
|
| 6 6.4 6.5
|
|
|
|
| 2015 2017 2018 2020
+---------------------------------------------------> Camunda
7.0 7.3 7.8 7.10 7.12 ^
|
| 同 團 隊
|
v
2017 2018 2020
+-------------------------------> Zeebe
0.1 0.14 0。22
如果從 GitHub 的 start 數看,Camunda 是遠遠沒有優勢的。以下數據是 2020-03-25 的數據。
- Activiti: 6.4k
- Flowable: 2.8k
- Camunda : 1.3k
在其他數據上的比較:
從功能上看呢?
CSDN 有一篇對比寫得很詳細:
我比較關注的點有以下幾個:
-
支持外部任務(External Task)
External Task 應該和 HTTP Task 做對比。
對於 HTTP Task ,在執行的時候會請求一個 HTTP API。等待這個請求結束后,流程繼續往下走。這里的問題是:
- API 超時如何處理?如果業務修改導致 API 處理時間變長時,要修改所有流程里配置的超時時間嗎?
- 如何區分測試環境和正式環境?
當 Camunda 執行到外部任務節點時,會發布一個任務單元。外部系統定時向 Camunda 獲取外部任務單元,然后做一些業務邏輯或者請求 HTTP API。做完之后,再提交給 Camunda,流程繼續往下走。
外部任務具有超時時間。這個時間后,其他客戶端請求接口可能獲取到該任務。但可以請求 API 延長超時時間。
一個外部任務只能被一個客戶端獲取,獲取后會加上一個鎖。除非超時,否則只有獲取到該任務的客戶端可以繼續操作。
外部任務可以配置優先級,並且這個優先級可以動態修改。
外部任務支持重試。當以任務處理失敗的方式提交給 Camunda 后,Camunda 會檢查配置的重試次數有多少,當前剩下多少。如果還有次數,則再次將該任務發布出去。
可以專門實現一個 External Task Client ,實現一套根據情況請求業務 API 的方式。雖然同樣是請求 HTTP API ,但是可以擁有更靈活的配置。
-
支持任意節點的跳轉
實際上 Camunda 不是直接支持跳轉。它支持取消某個節點的執行,也支持在任意節點創建一個執行。
如果要實現節點的跳轉,需要封裝兩個操作:
- 在目標節點創建一個執行
- 取消當前節點的執行
-
支持重啟(Restart)已經關閉的流程實例
雖然是叫重啟,但實際上是創建一個新實例,然后將已關閉的流程實例的信息復制一份到這個新實例。
-
支持流程實例的遷移(Migration)
隨着流程的更新,流程會有多個版本。每個流程實例會固定綁定一個流程版本,按照該版本的方式走。
Camunda 可以讓舊版本的流程實例遷移到其他版本的流程,目標流程版本可以是更新的,也可以是更舊的。
遷移分為兩步:- 生成遷移計划
- 執行遷移
執行遷移的時候,可以從遷移計划中選擇一部分流程實例做遷移。並且可以指定遷移后從哪個節點開始走(繼續)。
-
支持批量(Batch)操作的 API
例如批量掛起流程實例、批量激活流程實例、批量重啟流程實例
-
流程圖繪制工具有桌面版本
你可以把流程圖繪制工具下載到 Windows 系統上(其他系統也支持),繪制完流程圖后,通過這個工具把流程圖發布到 Camunda 。
你可以直接把這個軟件丟給需求方,讓他們把理想中的流程圖繪制出來。 Camunda 的流程繪制工具對業務方和開發者都是友好的。
甚至如果你不是為了將流程圖發布到 Camunda ,僅僅想繪制一個流程圖,這個工具也很好用。
Activiti 需要搭建后端服務才能通過 web 的方式繪制流程圖,而且它是偏向於開發者的。
除此之外, Camunda 和其他流程引擎一樣,支持以下功能:
-
定時節點(Timer Intermediate Catch Event)
可以選擇相對時間或者絕對時間。例如 10 分鍾之后繼續往下走或者 2021-11-11 的 11:11:11 的時候往下走。
時間的語法采用 ISO 8601 標准。這個標准在編程語言庫中基本都會支持。
可以設置時間常量,也可以引用流程引擎變量。在執行到定時節點之前設置或者修改時間。
-
網關節點(Gateway)
匯聚多個分支。不同網關有不同的作用。常用的互斥網關(Exclusive Gateway)表示與其相連的下游分支的條件中,一旦有一個分支的條件符合要求,就走那個分支,並且不再繼續判斷其他分支條件。
-
消息接收節點(Receive Task)
流程引擎在執行到該節點的時候,會等待一條消息。客戶端向該流程實例發送這條消息,流程繼續往下走。
-
執行監聽器(Execution Listener)
當以下事件發生時,會觸發一次通知:
- 流程實例的開始和結束
- 流程實例內一個節點的開始和結束
可以為 Camunda 寫一個擴展,用於通知流程實例的狀態。
參考:https://github.com/camunda/camunda-bpm-reactor/tree/master/examples/bpmn-execution-listener
從業務的角度上講,其他流程引擎滿足的部分 Camunda 也滿足,其他流程引擎不滿足的部分 Camunda 也滿足,因此選擇 Camunda 。
下一篇會詳細介紹一種基於 Camunda 做適配層的方案。
如果想快速了解 Camunda 的功能,可以下載 Camunda Modeler 了解其流程圖支持的各種組件,以及查看官方文檔。
直接訪問官方文檔會很慢,於是我把官方文檔做成 Docker 鏡像,可以下載到本地訪問。
docker pull schaepher/camunda-docs:latest
docker run -d -p "8080:80" schaepher/camunda-docs:latest
擴展閱讀
Camunda 官方文檔:
Camunda Rest API:
Activiti Rest API:
Camunda External Task:
https://docs.camunda.org/manual/latest/user-guide/process-engine/external-tasks/
Camunda Execution Listener:
https://docs.camunda.org/manual/latest/user-guide/process-engine/delegation-code/#execution-listener
Camunda Modeler(流程圖繪制工具):
Camunda Docs Docker Image: