工作流引擎在vivo營銷自動化中的應用實踐 | 引擎篇03
作者:vivo 互聯網伺服器團隊- Cheng Wangrong
本文是《vivo營銷自動化技術解密》的第4篇文章,分析了在營銷自動化業務引入工作流技術的背景和工作流引擎的介紹,同時介紹了幾種業界流行的開源工作流引擎特點,以及在項目自研開發過程中的設計思路和總結思考。
《vivo營銷自動化技術解密》系列文章:
一、業務背景
營銷自動化平台可以支援不同用戶生命周期的活動旅程策略配置 ,根據用戶觸發的不同活動行為,進行差異化的營銷觸達方案。同時各種類型活動的具體執行過程中也有不同的業務處理流程(比如審批流程和業務流轉)。
業務流程複雜多樣,需求變更頻繁,項目開發過程中會有以下痛點:
- 項目交付周期長:一個完整的業務流程需要從頭開始按版本迭代,開發時間長,成本高。
- 功能重複開發測試:業務之間會摻雜著很多共性的流程,導致大量重複性開發測試工作,效率低。
- 維護成本高:隨著項目業務的逐步發展,業務流程逐步積累,可維護性下降,系統改動牽一髮而動全身。
如何將業務邏輯從控制流中剝離出來,讓產研人員更聚焦於業務的實現是需要重點解決的問題。而傳統OA領域使用的是久經考驗的業務流程管理解決方案 —— 工作流(Workflow)。工作流是一套工業級的解決方案,由工作流管理聯盟(WfMC)制定了一系列的標準。
二、工作流介紹
2.1 工作流定義
工作流(Workflow)—— 對工作流程及其各操作步驟之間業務規則的抽象,將流程中的工作組織邏輯和規則進行建模,交由電腦進行自動處理。
工作流的本質思想是:通過預定義的工作流程模板,對現實活動進行實例化的過程。簡單說就是通過預設的格式或者可視化配置好流程的模板(比如一種分享活動的運行流程模板),使用時通過該模板構造出一個流程實例對象,通過實例對象完成活動運行跟蹤和回溯。
2.2 工作流參考模型
WfMC工作流管理聯盟為工作流制定了參考模型,其核心就是中間的工作流引擎,工作流引擎提供流程定義工具(介面1)、給使用者提供資訊查詢(介面2)、調用外部應用(介面3)、整合其他工作流(介面4)和監控管理(介面5)的能力。 對於大多數工作流產品而言,重點關注的是介面1和介面2的實現。
2.3 工作流引擎關鍵特性
- 流程可視化
提供可視化的流程搭建,流程視圖查看能力,以及實時觀測任務運行能力。
- 業務可編排復用
將公共業務進行組件化,可以支援任務的自由編排,自由搭建出適合的業務的不同流程。
- 業務和控制分離
將流程的控制(如流轉、判斷、循環、重試等)的任務交由工作流負責,讓使用者聚焦於核心業務邏輯。
2.4 工作流引擎的類型
對於工作流的類型沒有專門的標準,按照流程任務節點特性可以分為:
- 順序工作流
順序工作流的運行方式類似一種特定的流程圖,上一個流程任務完成後依次進入下一個流程任務,過程不可逆。
- 狀態機工作流
狀態機工作流側重關注的是流程任務的狀態,驅使任務狀態發生變化的因素一般為外部事件,即事件驅動的方式,驅使任務節點從一個狀態運行到另外一個狀態,節點間可逆。
- 規則驅動工作流
側重於節點的運轉規則,基於業務規則進行工作流程的執行,在處理具有明確目標但「規則」或規範級別不同的各種項目時,規則驅動的工作流非常有用。
可以看到不同類型的工作流不是完全割裂的,狀態機工作流中也可以結合著條件和規則進行操作節點轉換的過程。在軟體開發中,一般會考慮結合狀態機和規則驅動的工作流。
2.5 工作流引擎和狀態機的差異
在之前的文章裡面,我們有對狀態機和工作流引擎做過一次簡單的對比,事實上,兩者之間並不是一個完全對等的概念:
- 狀態機是系統狀態以及這些狀態之間轉移和動作等行為的數學計算模型,而工作流是對整體工作流程及其各操作步驟之間業務邏輯和規則的抽象建模。
- 狀態機模式是事件驅動型,大多通過外部事件觸髮狀態的自動流轉;工作流引擎更側重於描述預定義流程任務完成之後的自動流轉,可預測性會更強。
- 從適用場景的複雜性上看,直接使用狀態機的方式可以清晰地描繪出所有可能的狀態以及導致轉換的事件,適用於解決單維度、複雜度不高的業務問題,發揮靈活輕便的特點;工作流引擎則更適合複雜的業務流程管理,解決如大型CRM複雜度更高的流程自動化問題,聚焦於改善整體業務流程的效率。
- 工作流引擎是可以在狀態機的結構模型基礎上進行構建,事實上很多開源的工作流引擎也都是基於狀態機的實現方式。
了解了工作流的基本特點和使用場景之後,我們來看一下比較流行的開源工作流引擎。
三、開源工作流引擎
四、工作流引擎自研設計
4.1 使用開源工作流引擎的問題
- 開源工作流最大的優勢是可以藉助開源的資源,開箱即用,功能全面,但是與之帶來的是附帶的配置和表數量比較多的維護問題。以Activiti為例,使用Activiti7.0版本至少要引入二十多張表,雖然說看似是無侵入的方式,但是系統演進和維護過程中有一定的成本。特別是業務流程實例很多的時候,開發人員需要對錶邏輯有更深的把控。
- 由於業務的客觀獨特性,作為業務流程組件,一般都需要根據自身業務進行二次開發適配。 比如需要根據自身組織架構,進行流程節點用戶角色許可權的管控;將自身的業務能力插件化,加入工作流程配置中,進行攔截回調等。
4.2 自研引擎核心設計思路
4.2.1 引擎核心模組
回歸工作流的本質, 工作流是通過預定義的流程模板,對現實活動進行實例化的過程。一個基本的工作流引擎主要包括三大核心部分:
- 流程模板創建
根據業務規則和邏輯,創建流程模板,設置每一個節點的操作和變更路徑。基於模板創建,可以延伸出流程設計器、插件式節點,多樣化的模板文件格式、模板持久化等。
- 流程實例發布
根據流程模板,創建一個流程實例,流程模板和流程實例的關係類似類和對象的關係。比如說工單系統管理員定義好一個審批流模板(流程模板),用戶點擊創建一個工單(流程實例)。基於流程實例發布,又可以延伸出實例實時觀測,節點變遷記錄回溯,實例狀態持久化,失敗重試,事務控制等。
- 任務流程執行
創建好流程實例之後,流程實例只需要按照流程模板的定義獨立執行各自實例的任務,不同的實例之間互不影響,完成各自實例的生命周期。
4.2.2 引擎核心設計
① 應用容器啟動時,載入流程引擎環境配置,包括解析器構造,流程引擎上下文,流程定義文件路徑等。
② 讀取定好的流程定義文件,進行流程節點解析,構建好執行上下文,將流程節點放到記憶體快取中。
③ 業務側進行流程創建,啟動一個新的流程實例,同時將業務流程和流程實例進行綁定。
④ 運行流程實例各個節點,將每個流程節點進行持久化保存。
4.3 具體實踐
① 引擎核心服務。
引擎操作的主要對外介面,包括啟動流程實例,和獲取相關流程定義模板,流程實例,流程節點的服務。
public interface FlowEngine {
/**
* 根據流程定義key,參數列表啟動流程實例
*
*/
FlowInstance startInstance(String processDefKey, Map<String, Object> args);
/**
* 根據流程定義主鍵ID,參數列表執行流程任務(推動流程自動流轉)
* 統一事務控制
*/
void execInstance(Long instanceId, Map<String, Object> args) throws FlowAuthorityException;
/**
* 獲取流程定義process服務
*
*/
ProcessService process();
/**
* 獲取流程實例服務
*
*/
InstanceService instance();
/**
* 獲取任務節點服務
*
*/
TaskService task();
}
② 流程定義服務。
主要是針對流程定義模板的創建和發布,可以根據具體的實現類來支援不同的創建方式。
public interface ProcessService {
/**
* 創建流程定義模板
*
*/
void create(String definition);
/**
* 發布流程定義模板
*
*/
void deploy(String fileName);
/**
* 獲取流程key對應的流程定義
*/
FlowProcess getProcessByDefKey(String processDefKey);
}
③ 流程實例服務。
提供流程實例創建持久化和流程實例執行的入口。
public interface InstanceService {
/**
* 創建流程實例
*
*/
FlowInstance createInstance(FlowProcess process, Map<String, Object> args);
/**
* 執行流程實例
*
* @param instanceId 流程實例id
*/
void exec(Long instanceId);
/**
* 根據id獲取流程實例
*
* @param instanceId
* @return
*/
FlowInstance getById(Long instanceId);
}
④ 流程任務節點服務。
提供流程節點具體每個任務的創建和查詢。
public interface TaskService {
/**
* 根據任務模型、執行對象創建新的任務
*
*/
FlowTask createTask(TaskModel taskModel, Execution execution);
/**
* 完成任務
*
*/
FlowTask complete(Long taskId, Map<String, Object> args);
/**
* 獲取流程實例中正在進行的任務
*
*/
FlowTask getActiveTask(Long instanceId);
/**
* 獲取流程實例上一個已完成的任務
*
*/
FlowHistTask getLastDoneTask(Long instanceId);
}
其中核心的方法就是
FlowEngine#startInstanceByKey,啟動流程實例。基於流程定義,創建一個流程實例對象。
FlowEngine#execInstance,執行流程實例任務,通過傳入的上下文參數(操作人,操作變數等),按照流程定義的節點任務,推進流程實例的自動流轉。
4.4 思考和擴展
- 流程定義解析性能。
由於目前設計是在應用啟動時對所有的流程定義文件進行載入和解析,流程定義文件過多時會影響應用啟動速度,可以通過多執行緒解析和懶載入(使用時解析)兩種方式進行優化。
- 流程定義版本兼容性。
由於業務流程不是一成不變的,在項目發展過程中會不斷進行迭代,需要對前面不同的流程進行兼容。
- 流程節點插件化和編排能力。
將基礎服務進行提取公用,以支援繪製不同流程的插件化和編排能力。
- 流程執行監控能力。
對流程任務節點執行情況進行埋點上報,系統自動進行監測告警。
五、總結
本文分析了引入工作流引擎的背景,驅使業務邏輯從控制流中剝離出來,讓產研團隊更聚焦於業務,解決研發效率低的問題。
工作流的本質思想是通過預定義的工作流程模板,對現實活動進行實例化的過程。一般需要具備流程可視化、業務可編排復用、 業務和控制分離的基本能力。一般常見的工作流分為順序工作流、狀態機工作流和規則驅動工作流,開源工作流框架中最常見的是狀態機工作流,利用事件驅動的方式,驅使流程運轉。
同時簡單介紹了業界比較流行的幾種開源工作流引擎的特點,結合開源工作流引擎的特點的問題,並且針對多樣化和迭代頻繁的業務流程, 以工作流的本質思想為出發點,我們自研了一套輕量級的工作流引擎,分享了在實踐過程中的設計思路和總結思考。