作者:vivo 互聯(lián)網(wǎng)服務(wù)器團(tuán)隊- Cheng Wangrong
本文是《vivo營銷自動化技術(shù)解密》的第4篇文章,分析了在營銷自動化業(yè)務(wù)引入工作流技術(shù)的背景和工作流引擎的介紹秽澳,同時介紹了幾種業(yè)界流行的開源工作流引擎特點(diǎn)淹冰,以及在項目自研開發(fā)過程中的設(shè)計思路和總結(jié)思考。
《vivo營銷自動化技術(shù)解密》系列文章:
一奸焙、業(yè)務(wù)背景
營銷自動化平臺可以支持不同用戶生命周期的活動旅程策略配置 智袭,根據(jù)用戶觸發(fā)的不同活動行為,進(jìn)行差異化的營銷觸達(dá)方案蜻底。同時各種類型活動的具體執(zhí)行過程中也有不同的業(yè)務(wù)處理流程(比如審批流程和業(yè)務(wù)流轉(zhuǎn))。
業(yè)務(wù)流程復(fù)雜多樣瓷耙,需求變更頻繁朱躺,項目開發(fā)過程中會有以下痛點(diǎn):
- 項目交付周期長:一個完整的業(yè)務(wù)流程需要從頭開始按版本迭代,開發(fā)時間長搁痛,成本高长搀。
- 功能重復(fù)開發(fā)測試:業(yè)務(wù)之間會摻雜著很多共性的流程,導(dǎo)致大量重復(fù)性開發(fā)測試工作鸡典,效率低源请。
- 維護(hù)成本高:隨著項目業(yè)務(wù)的逐步發(fā)展,業(yè)務(wù)流程逐步積累彻况,可維護(hù)性下降谁尸,系統(tǒng)改動牽一發(fā)而動全身。
如何將業(yè)務(wù)邏輯從控制流中剝離出來纽甘,讓產(chǎn)研人員更聚焦于業(yè)務(wù)的實(shí)現(xiàn)是需要重點(diǎn)解決的問題良蛮。而傳統(tǒng)OA領(lǐng)域使用的是久經(jīng)考驗的業(yè)務(wù)流程管理解決方案 —— 工作流(Workflow)。工作流是一套工業(yè)級的解決方案悍赢,由工作流管理聯(lián)盟(WfMC)制定了一系列的標(biāo)準(zhǔn)决瞳。
二、工作流介紹
2.1 工作流定義
工作流(Workflow)—— 對工作流程及其各操作步驟之間業(yè)務(wù)規(guī)則的抽象左权,將流程中的工作組織邏輯和規(guī)則進(jìn)行建模皮胡,交由計算機(jī)進(jìn)行自動處理。
工作流的本質(zhì)思想是:通過預(yù)定義的工作流程模板赏迟,對現(xiàn)實(shí)活動進(jìn)行實(shí)例化的過程屡贺。簡單說就是通過預(yù)設(shè)的格式或者可視化配置好流程的模板(比如一種分享活動的運(yùn)行流程模板),使用時通過該模板構(gòu)造出一個流程實(shí)例對象锌杀,通過實(shí)例對象完成活動運(yùn)行跟蹤和回溯甩栈。
2.2 工作流參考模型
WfMC工作流管理聯(lián)盟為工作流制定了參考模型,其核心就是中間的工作流引擎糕再,工作流引擎提供流程定義工具(接口1)谤职、給使用者提供信息查詢(接口2)、調(diào)用外部應(yīng)用(接口3)亿鲜、整合其他工作流(接口4)和監(jiān)控管理(接口5)的能力允蜈。 對于大多數(shù)工作流產(chǎn)品而言,重點(diǎn)關(guān)注的是接口1和接口2的實(shí)現(xiàn)蒿柳。
2.3 工作流引擎關(guān)鍵特性
- 流程可視化
提供可視化的流程搭建饶套,流程視圖查看能力,以及實(shí)時觀測任務(wù)運(yùn)行能力垒探。
- 業(yè)務(wù)可編排復(fù)用
將公共業(yè)務(wù)進(jìn)行組件化妓蛮,可以支持任務(wù)的自由編排,自由搭建出適合的業(yè)務(wù)的不同流程圾叼。
- 業(yè)務(wù)和控制分離
將流程的控制(如流轉(zhuǎn)蛤克、判斷捺癞、循環(huán)、重試等)的任務(wù)交由工作流負(fù)責(zé)构挤,讓使用者聚焦于核心業(yè)務(wù)邏輯髓介。
2.4 工作流引擎的類型
對于工作流的類型沒有專門的標(biāo)準(zhǔn),按照流程任務(wù)節(jié)點(diǎn)特性可以分為:
- 順序工作流
順序工作流的運(yùn)行方式類似一種特定的流程圖筋现,上一個流程任務(wù)完成后依次進(jìn)入下一個流程任務(wù)唐础,過程不可逆。
- 狀態(tài)機(jī)工作流
狀態(tài)機(jī)工作流側(cè)重關(guān)注的是流程任務(wù)的狀態(tài)矾飞,驅(qū)使任務(wù)狀態(tài)發(fā)生變化的因素一般為外部事件一膨,即事件驅(qū)動的方式,驅(qū)使任務(wù)節(jié)點(diǎn)從一個狀態(tài)運(yùn)行到另外一個狀態(tài)洒沦,節(jié)點(diǎn)間可逆豹绪。
- 規(guī)則驅(qū)動工作流
側(cè)重于節(jié)點(diǎn)的運(yùn)轉(zhuǎn)規(guī)則,基于業(yè)務(wù)規(guī)則進(jìn)行工作流程的執(zhí)行申眼,在處理具有明確目標(biāo)但“規(guī)則”或規(guī)范級別不同的各種項目時森篷,規(guī)則驅(qū)動的工作流非常有用。
可以看到不同類型的工作流不是完全割裂的豺型,狀態(tài)機(jī)工作流中也可以結(jié)合著條件和規(guī)則進(jìn)行操作節(jié)點(diǎn)轉(zhuǎn)換的過程仲智。在軟件開發(fā)中,一般會考慮結(jié)合狀態(tài)機(jī)和規(guī)則驅(qū)動的工作流姻氨。
2.5 工作流引擎和狀態(tài)機(jī)的差異
在之前的文章里面钓辆,我們有對狀態(tài)機(jī)和工作流引擎做過一次簡單的對比,事實(shí)上肴焊,兩者之間并不是一個完全對等的概念:
- 狀態(tài)機(jī)是系統(tǒng)狀態(tài)以及這些狀態(tài)之間轉(zhuǎn)移和動作等行為的數(shù)學(xué)計算模型前联,而工作流是對整體工作流程及其各操作步驟之間業(yè)務(wù)邏輯和規(guī)則的抽象建模。
- 狀態(tài)機(jī)模式是事件驅(qū)動型娶眷,大多通過外部事件觸發(fā)狀態(tài)的自動流轉(zhuǎn)似嗤;工作流引擎更側(cè)重于描述預(yù)定義流程任務(wù)完成之后的自動流轉(zhuǎn),可預(yù)測性會更強(qiáng)届宠。
- 從適用場景的復(fù)雜性上看烁落,直接使用狀態(tài)機(jī)的方式可以清晰地描繪出所有可能的狀態(tài)以及導(dǎo)致轉(zhuǎn)換的事件,適用于解決單維度豌注、復(fù)雜度不高的業(yè)務(wù)問題伤塌,發(fā)揮靈活輕便的特點(diǎn);工作流引擎則更適合復(fù)雜的業(yè)務(wù)流程管理轧铁,解決如大型CRM復(fù)雜度更高的流程自動化問題每聪,聚焦于改善整體業(yè)務(wù)流程的效率。
- 工作流引擎是可以在狀態(tài)機(jī)的結(jié)構(gòu)模型基礎(chǔ)上進(jìn)行構(gòu)建,事實(shí)上很多開源的工作流引擎也都是基于狀態(tài)機(jī)的實(shí)現(xiàn)方式药薯。
了解了工作流的基本特點(diǎn)和使用場景之后绑洛,我們來看一下比較流行的開源工作流引擎。
三童本、開源工作流引擎
四真屯、工作流引擎自研設(shè)計
4.1 使用開源工作流引擎的問題
- 開源工作流最大的優(yōu)勢是可以借助開源的資源,開箱即用巾陕,功能全面讨跟,但是與之帶來的是附帶的配置和表數(shù)量比較多的維護(hù)問題纪他。以Activiti為例鄙煤,使用Activiti7.0版本至少要引入二十多張表,雖然說看似是無侵入的方式茶袒,但是系統(tǒng)演進(jìn)和維護(hù)過程中有一定的成本梯刚。特別是業(yè)務(wù)流程實(shí)例很多的時候,開發(fā)人員需要對表邏輯有更深的把控薪寓。
- 由于業(yè)務(wù)的客觀獨(dú)特性亡资,作為業(yè)務(wù)流程組件,一般都需要根據(jù)自身業(yè)務(wù)進(jìn)行二次開發(fā)適配向叉。 比如需要根據(jù)自身組織架構(gòu)锥腻,進(jìn)行流程節(jié)點(diǎn)用戶角色權(quán)限的管控;將自身的業(yè)務(wù)能力插件化母谎,加入工作流程配置中瘦黑,進(jìn)行攔截回調(diào)等。
4.2 自研引擎核心設(shè)計思路
4.2.1 引擎核心模塊
回歸工作流的本質(zhì)奇唤, 工作流是通過預(yù)定義的流程模板幸斥,對現(xiàn)實(shí)活動進(jìn)行實(shí)例化的過程。一個基本的工作流引擎主要包括三大核心部分:
- 流程模板創(chuàng)建
根據(jù)業(yè)務(wù)規(guī)則和邏輯咬扇,創(chuàng)建流程模板甲葬,設(shè)置每一個節(jié)點(diǎn)的操作和變更路徑⌒负兀基于模板創(chuàng)建经窖,可以延伸出流程設(shè)計器、插件式節(jié)點(diǎn)梭灿,多樣化的模板文件格式钠至、模板持久化等。
- 流程實(shí)例發(fā)布
根據(jù)流程模板胎源,創(chuàng)建一個流程實(shí)例棉钧,流程模板和流程實(shí)例的關(guān)系類似類和對象的關(guān)系。比如說工單系統(tǒng)管理員定義好一個審批流模板(流程模板)涕蚤,用戶點(diǎn)擊創(chuàng)建一個工單(流程實(shí)例)宪卿〉乃校基于流程實(shí)例發(fā)布,又可以延伸出實(shí)例實(shí)時觀測佑钾,節(jié)點(diǎn)變遷記錄回溯西疤,實(shí)例狀態(tài)持久化,失敗重試休溶,事務(wù)控制等代赁。
- 任務(wù)流程執(zhí)行
創(chuàng)建好流程實(shí)例之后,流程實(shí)例只需要按照流程模板的定義獨(dú)立執(zhí)行各自實(shí)例的任務(wù)兽掰,不同的實(shí)例之間互不影響芭碍,完成各自實(shí)例的生命周期。
4.2.2 引擎核心設(shè)計
① 應(yīng)用容器啟動時孽尽,加載流程引擎環(huán)境配置窖壕,包括解析器構(gòu)造,流程引擎上下文杉女,流程定義文件路徑等瞻讽。
② 讀取定好的流程定義文件,進(jìn)行流程節(jié)點(diǎn)解析熏挎,構(gòu)建好執(zhí)行上下文速勇,將流程節(jié)點(diǎn)放到內(nèi)存緩存中。
③ 業(yè)務(wù)側(cè)進(jìn)行流程創(chuàng)建坎拐,啟動一個新的流程實(shí)例烦磁,同時將業(yè)務(wù)流程和流程實(shí)例進(jìn)行綁定。
④ 運(yùn)行流程實(shí)例各個節(jié)點(diǎn)廉白,將每個流程節(jié)點(diǎn)進(jìn)行持久化保存个初。
4.3 具體實(shí)踐
① 引擎核心服務(wù)。
引擎操作的主要對外接口猴蹂,包括啟動流程實(shí)例院溺,和獲取相關(guān)流程定義模板,流程實(shí)例磅轻,流程節(jié)點(diǎn)的服務(wù)珍逸。
public interface FlowEngine {
/**
* 根據(jù)流程定義key,參數(shù)列表啟動流程實(shí)例
*
*/
FlowInstance startInstance(String processDefKey, Map<String, Object> args);
/**
* 根據(jù)流程定義主鍵ID聋溜,參數(shù)列表執(zhí)行流程任務(wù)(推動流程自動流轉(zhuǎn))
* 統(tǒng)一事務(wù)控制
*/
void execInstance(Long instanceId, Map<String, Object> args) throws FlowAuthorityException;
/**
* 獲取流程定義process服務(wù)
*
*/
ProcessService process();
/**
* 獲取流程實(shí)例服務(wù)
*
*/
InstanceService instance();
/**
* 獲取任務(wù)節(jié)點(diǎn)服務(wù)
*
*/
TaskService task();
}
② 流程定義服務(wù)谆膳。
主要是針對流程定義模板的創(chuàng)建和發(fā)布,可以根據(jù)具體的實(shí)現(xiàn)類來支持不同的創(chuàng)建方式撮躁。
public interface ProcessService {
/**
* 創(chuàng)建流程定義模板
*
*/
void create(String definition);
/**
* 發(fā)布流程定義模板
*
*/
void deploy(String fileName);
/**
* 獲取流程key對應(yīng)的流程定義
*/
FlowProcess getProcessByDefKey(String processDefKey);
}
③ 流程實(shí)例服務(wù)漱病。
提供流程實(shí)例創(chuàng)建持久化和流程實(shí)例執(zhí)行的入口。
public interface InstanceService {
/**
* 創(chuàng)建流程實(shí)例
*
*/
FlowInstance createInstance(FlowProcess process, Map<String, Object> args);
/**
* 執(zhí)行流程實(shí)例
*
* @param instanceId 流程實(shí)例id
*/
void exec(Long instanceId);
/**
* 根據(jù)id獲取流程實(shí)例
*
* @param instanceId
* @return
*/
FlowInstance getById(Long instanceId);
}
④ 流程任務(wù)節(jié)點(diǎn)服務(wù)。
提供流程節(jié)點(diǎn)具體每個任務(wù)的創(chuàng)建和查詢杨帽。
public interface TaskService {
/**
* 根據(jù)任務(wù)模型漓穿、執(zhí)行對象創(chuàng)建新的任務(wù)
*
*/
FlowTask createTask(TaskModel taskModel, Execution execution);
/**
* 完成任務(wù)
*
*/
FlowTask complete(Long taskId, Map<String, Object> args);
/**
* 獲取流程實(shí)例中正在進(jìn)行的任務(wù)
*
*/
FlowTask getActiveTask(Long instanceId);
/**
* 獲取流程實(shí)例上一個已完成的任務(wù)
*
*/
FlowHistTask getLastDoneTask(Long instanceId);
}
其中核心的方法就是
FlowEngine#startInstanceByKey,啟動流程實(shí)例注盈』挝#基于流程定義,創(chuàng)建一個流程實(shí)例對象老客。
FlowEngine#execInstance僚饭,執(zhí)行流程實(shí)例任務(wù),通過傳入的上下文參數(shù)(操作人胧砰,操作變量等)鳍鸵,按照流程定義的節(jié)點(diǎn)任務(wù),推進(jìn)流程實(shí)例的自動流轉(zhuǎn)朴则。
4.4 思考和擴(kuò)展
- 流程定義解析性能权纤。
由于目前設(shè)計是在應(yīng)用啟動時對所有的流程定義文件進(jìn)行加載和解析钓简,流程定義文件過多時會影響應(yīng)用啟動速度乌妒,可以通過多線程解析和懶加載(使用時解析)兩種方式進(jìn)行優(yōu)化。
- 流程定義版本兼容性外邓。
由于業(yè)務(wù)流程不是一成不變的撤蚊,在項目發(fā)展過程中會不斷進(jìn)行迭代,需要對前面不同的流程進(jìn)行兼容损话。
- 流程節(jié)點(diǎn)插件化和編排能力侦啸。
將基礎(chǔ)服務(wù)進(jìn)行提取公用,以支持繪制不同流程的插件化和編排能力丧枪。
- 流程執(zhí)行監(jiān)控能力光涂。
對流程任務(wù)節(jié)點(diǎn)執(zhí)行情況進(jìn)行埋點(diǎn)上報,系統(tǒng)自動進(jìn)行監(jiān)測告警拧烦。
五忘闻、總結(jié)
本文分析了引入工作流引擎的背景,驅(qū)使業(yè)務(wù)邏輯從控制流中剝離出來恋博,讓產(chǎn)研團(tuán)隊更聚焦于業(yè)務(wù)齐佳,解決研發(fā)效率低的問題。
工作流的本質(zhì)思想是通過預(yù)定義的工作流程模板债沮,對現(xiàn)實(shí)活動進(jìn)行實(shí)例化的過程炼吴。一般需要具備流程可視化、業(yè)務(wù)可編排復(fù)用疫衩、 業(yè)務(wù)和控制分離的基本能力硅蹦。一般常見的工作流分為順序工作流、狀態(tài)機(jī)工作流和規(guī)則驅(qū)動工作流,開源工作流框架中最常見的是狀態(tài)機(jī)工作流童芹,利用事件驅(qū)動的方式命爬,驅(qū)使流程運(yùn)轉(zhuǎn)趟咆。
同時簡單介紹了業(yè)界比較流行的幾種開源工作流引擎的特點(diǎn)垄分,結(jié)合開源工作流引擎的特點(diǎn)的問題,并且針對多樣化和迭代頻繁的業(yè)務(wù)流程概作, 以工作流的本質(zhì)思想為出發(fā)點(diǎn)嗜价,我們自研了一套輕量級的工作流引擎艇抠,分享了在實(shí)踐過程中的設(shè)計思路和總結(jié)思考。