前言
在每個(gè)公司的系統(tǒng)中,總有一些擁有復(fù)雜業(yè)務(wù)邏輯的系統(tǒng)视译,這些系統(tǒng)承載著核心業(yè)務(wù)邏輯蕊唐,幾乎每個(gè)需求都和這些核心業(yè)務(wù)有關(guān),這些核心業(yè)務(wù)業(yè)務(wù)邏輯冗長简十,涉及內(nèi)部邏輯運(yùn)算檬某,緩存操作,持久化操作螟蝙,外部資源調(diào)取恢恼,內(nèi)部其他系統(tǒng)RPC調(diào)用等等。時(shí)間一長胰默,項(xiàng)目幾經(jīng)易手场斑,維護(hù)的成本得就會(huì)越來越高。各種硬代碼判斷牵署,分支條件越來越多漏隐。代碼的抽象,復(fù)用率也越來越低奴迅,各個(gè)模塊之間的耦合度很高青责。一小段邏輯的變動(dòng),會(huì)影響到其他模塊,需要進(jìn)行完整回歸測試來驗(yàn)證脖隶。如要靈活改變業(yè)務(wù)流程的順序扁耐,則要進(jìn)行代碼大改動(dòng)進(jìn)行抽象,重新寫方法浩村。實(shí)時(shí)熱變更業(yè)務(wù)流程做葵?幾乎很難實(shí)現(xiàn)。
開源解決方案
說到流程引擎心墅,開源界有大名鼎鼎的老牌開源軟件JBPM酿矢,也有近幾年非常流行的Activiti和Flowable。他們都是基于BPM協(xié)議怎燥,可以做到基于角色任務(wù)的流傳瘫筐,邏輯的流轉(zhuǎn)。并且很多基于BPM協(xié)議的編輯工具都能做可視化的編輯铐姚。
但今天我要介紹的策肝,是一款輕量級(jí)的流程編排框架——Liteflow。
Liteflow主要致力于邏輯驅(qū)動(dòng)的編排隐绵≈冢可以滿足于大部分的生產(chǎn)業(yè)務(wù)場景。和以上著名的開源流程引擎相比依许,雖然不如他們那么全面棺禾,但是勝在輕量,高性能和極少的學(xué)習(xí)成本峭跳。而且這些項(xiàng)目都是國外開源項(xiàng)目膘婶,集成起來相對比較重,文檔本地化也做的不夠好蛀醉。Liteflow擁有完善的本地文檔和使用范例悬襟。能幫助你的核心系統(tǒng)變得更加靈活,更加易擴(kuò)展拯刁。是一個(gè)解耦你系統(tǒng)的利器脊岳。
Liteflow框架的作用
Liteflow就是為解耦復(fù)雜邏輯而生,如果你要對復(fù)雜業(yè)務(wù)邏輯進(jìn)行新寫或者重構(gòu)垛玻,用liteflow最合適不過割捅。它是一個(gè)輕量,快速的組件式流程引擎框架夭谤,組件編排,幫助解耦業(yè)務(wù)代碼巫糙,讓每一個(gè)業(yè)務(wù)片段都是一個(gè)組件朗儒。
使用Liteflow,你需要去把復(fù)雜的業(yè)務(wù)邏輯按代碼片段拆分成一個(gè)個(gè)小組件,并定義一個(gè)規(guī)則流程配置醉锄。這樣乏悄,所有的組件,就能按照你的規(guī)則配置去進(jìn)行復(fù)雜的流轉(zhuǎn)恳不。同時(shí)Liteflow支持規(guī)則文件的熱加載檩小,即時(shí)完成修改生效。并提供多種持久化規(guī)則的方式的擴(kuò)展烟勋。
Liteflow的設(shè)計(jì)原則
Liteflow是基于工作臺(tái)模式進(jìn)行設(shè)計(jì)的规求,何謂工作臺(tái)模式?
n個(gè)工人按照一定順序圍著一張工作臺(tái)卵惦,按順序各自生產(chǎn)零件阻肿,生產(chǎn)的零件最終能組裝成一個(gè)機(jī)器,每個(gè)工人只需要完成自己手中零件的生產(chǎn)沮尿,而無需知道其他工人生產(chǎn)的內(nèi)容丛塌。每一個(gè)工人生產(chǎn)所需要的資源都從工作臺(tái)上拿取,如果工作臺(tái)上有生產(chǎn)所必須的資源畜疾,則就進(jìn)行生產(chǎn)赴邻,若是沒有,就等到有這個(gè)資源啡捶。每個(gè)工人所做好的零件姥敛,也都放在工作臺(tái)上。
這個(gè)模式有幾個(gè)好處:
- 每個(gè)工人無需和其他工人進(jìn)行溝通届慈。工人只需要關(guān)心自己的工作內(nèi)容和工作臺(tái)上的資源徒溪。這樣就做到了每個(gè)工人之間的解耦和無差異性。
- 即便是工人之間調(diào)換位置金顿,工人的工作內(nèi)容和關(guān)心的資源沒有任何變化臊泌。這樣就保證了每個(gè)工人的穩(wěn)定性。
- 如果是指派某個(gè)工人去其他的工作臺(tái)揍拆,工人的工作內(nèi)容和需要的資源依舊沒有任何變化渠概,這樣就做到了工人的可復(fù)用性。
- 因?yàn)槊總€(gè)工人不需要和其他工人溝通嫂拴,所以可以在生產(chǎn)任務(wù)進(jìn)行時(shí)進(jìn)行實(shí)時(shí)工位更改:替換播揪,插入,撤掉一些工人筒狠,這樣生產(chǎn)任務(wù)也能實(shí)時(shí)的被更改猪狈。這樣就保證了整個(gè)生產(chǎn)任務(wù)的靈活性。
這個(gè)模式映射到Liteflow框架里辩恼,工人就是組件雇庙,工人坐的順序就是流程配置谓形,工作臺(tái)就是上下文,資源就是參數(shù)疆前,最終組裝的這個(gè)機(jī)器就是這個(gè)業(yè)務(wù)寒跳。正因?yàn)橛羞@些特性,所以Liteflow能做到統(tǒng)一解耦的組件和靈活的裝配竹椒。
springboot里快速配置
Liteflow支持了springboot的自動(dòng)裝配童太,當(dāng)然Liteflow也為非springboot和非spring的項(xiàng)目也提供了支持,這里僅以springboot項(xiàng)目為示例進(jìn)行介紹:
依賴最新的依賴包:
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
<version>2.3.3</version>
</dependency>
配置上規(guī)則路徑:
liteflow.rule-source=config/flow.xml
定義組件
Liteflow希望用戶把復(fù)雜邏輯拆分成一個(gè)個(gè)可復(fù)用的組件胸完,所以你得定義你的組件书释,組件的定義很簡單,你需要繼承NodeComponent
類舶吗,然后實(shí)現(xiàn)process
方法就行征冷,以下為示例:
@Component("test")
public class TestComponent extends NodeComponent {
@Override
public void process() {
Slot slot = this.getSlot();//slot為這個(gè)請求的上下文
//這里為你的業(yè)務(wù)處理邏輯
}
}
這里會(huì)有童鞋問,我的業(yè)務(wù)方法需要入?yún)⒑统鰠⒃趺崔k誓琼,如何傳遞呢检激?
Liteflow為每個(gè)線程都自動(dòng)分配了唯一的一個(gè)slot,可以理解為上下文腹侣。想一想上面說的那個(gè)模型叔收,每個(gè)組件不需要和其他組件進(jìn)行信息互通,所需要的參數(shù)從slot里取就是了傲隶,同時(shí)饺律,執(zhí)行完業(yè)務(wù)邏輯之后,把結(jié)果也放入slot里跺株。所以每個(gè)組件都是獨(dú)立的無參構(gòu)造复濒,這樣就消除了每個(gè)組件的差異性。
這里的slot能貫穿所有組件乒省,每一個(gè)組件都可以訪問到slot里所有的數(shù)據(jù)巧颈。當(dāng)然每個(gè)請求之間的slot,Liteflow做了嚴(yán)格的隔離袖扛,不用擔(dān)心數(shù)據(jù)會(huì)串的問題砸泛。
Liteflow提供的默認(rèn)Slot是一個(gè)弱類型的對象,這里建議使用者自己定義一個(gè)值對象蛆封,只需要繼承AbsSlot
類唇礁,便可成為你自己的Slot。更加貼合業(yè)務(wù)惨篱。
組件除了必須要實(shí)現(xiàn)的process
方法盏筐,還有幾個(gè)可選實(shí)現(xiàn):
isAccess:表示是否進(jìn)入該節(jié)點(diǎn),可以用于業(yè)務(wù)參數(shù)的預(yù)先判斷
isContinueOnError:表示出錯(cuò)是否繼續(xù)往下執(zhí)行下一個(gè)組件砸讳,默認(rèn)為false
isEnd:表示是否立即結(jié)束整個(gè)流程 琢融,默認(rèn)為false楷拳,也可以在業(yè)務(wù)日志里根據(jù)業(yè)務(wù)判斷來調(diào)用this.setIsEnd(true)來結(jié)束整個(gè)流程。
@Component("test")
public class TestComponent extends NodeComponent {
@Override
public void process() {
Slot slot = this.getSlot();//slot為這個(gè)請求的上下文
//這里為你的業(yè)務(wù)處理邏輯
}
@Override
public boolean isAccess() {
Slot slot = this.getSlot();
//這里做你的參數(shù)檢查吏奸,如果沒獲取到必須的業(yè)務(wù)參數(shù),就不會(huì)進(jìn)入該組件
boolean checkResult = true;//模擬檢查結(jié)果為true
return checkResult;
}
@Override
public boolean isContinueOnError() {
return super.isContinueOnError();//默認(rèn)為false
}
@Override
public boolean isEnd() {
return super.isEnd();//默認(rèn)為false
}
}
你只需定義你的業(yè)務(wù)組件陶耍,之后奋蔚,在啟動(dòng)時(shí),Liteflow會(huì)自動(dòng)掃描到你定義的所有組件烈钞,并進(jìn)行加載泊碑。
編輯規(guī)則文件
實(shí)現(xiàn)完了組件之后,你需要定義規(guī)則文件毯欣,之前規(guī)則文件的路徑配置在了config/flow.xml
中馒过,所以我們要編輯這個(gè)文件。
Liteflow的規(guī)則文件定義非常簡單好理解酗钞。簡單的配置腹忽,但是能覆蓋大部分的應(yīng)用場景。
先來看一個(gè)示例:
<chain name="chain1">
<then value="a,c"/>
<when value="b,d"/>
<then value="e,f,g"/>
</chain>
在Liteflow中砚作,定義了then和when兩種線程執(zhí)行方式窘奏,then代表串行,上面的示例中葫录,c必須要等a執(zhí)行完才能執(zhí)行着裹。when代表并行,上面的示例中米同,b,d同時(shí)執(zhí)行骇扇。并且b,d都執(zhí)行完了,下面的e面粮,f少孝,g才能挨個(gè)順序執(zhí)行。
再來看個(gè)稍微復(fù)雜點(diǎn)的:
<chain name="chain1">
<then value="a,c(b|d)"/>
<then value="e,f,g"/>
</chain>
Liteflow提供了條件組件但金,這種節(jié)點(diǎn)的職責(zé)就是路由韭山,根據(jù)業(yè)務(wù)邏輯來路由到b節(jié)點(diǎn)還是d節(jié)點(diǎn)。
條件組件的定義示例如下冷溃,需要去繼承NodeCondComponent
這個(gè)類钱磅,最終返回的b就是最終要路由到的節(jié)點(diǎn)
@Component("c")
public class CComponent extends NodeCondComponent {
@Override
public String processCond() throws Exception {
//你的業(yè)務(wù)邏輯
return "b";
}
}
Liteflow允許你編輯嵌套的流程,例子如下:
<chain name="chain1">
<then value="a,c,strategy1,g"/>
</chain>
<chain name="strategy1">
<then value="m(m1|m2|strategy2)"/>
</chain>
<chain name="strategy2">
<then value="q,p(p1|p2)"/>
</chain>
在這個(gè)例子中似枕,這3條鏈路是串起來執(zhí)行的盖淡,在xml里,可以寫你的組件id凿歼,也可以寫流程id褪迟。配合之前的例子冗恨,是不是能表達(dá)的流程就更加豐富了點(diǎn)呢。
以上3個(gè)例子涵蓋了Liteflow最主要的功能味赃,當(dāng)然Liteflow還提供一些其他的特性掀抹,比如如何進(jìn)行循環(huán)執(zhí)行,如何打印步驟心俗,并且Liteflow還提供了一個(gè)簡易的監(jiān)控模塊傲武,用于統(tǒng)計(jì)你的組件執(zhí)行情況。這里就不一一介紹了城榛。具體你可以點(diǎn)擊Liteflow的Gitee主頁進(jìn)行查看:
示例工程
為了方便用戶的使用揪利,Liteflow在項(xiàng)目里提供了一個(gè)測試用例,你可以直接拿來跑:
同時(shí)作者還做了一個(gè)帶簡單業(yè)務(wù)的示例工程狠持,來演示如何具體實(shí)踐:
這個(gè)簡單業(yè)務(wù)是一個(gè)電商場景的價(jià)格計(jì)算的案例疟位,如何通過拆分組件來組合不同的影響價(jià)格的業(yè)務(wù)。并且這個(gè)示例工程還提供了一個(gè)簡單的頁面供大家進(jìn)行調(diào)試:
最后
在流程編排開源上喘垂,國內(nèi)一直沒有特別著名的開源項(xiàng)目甜刻。Liteflow的體量雖然無法和業(yè)界著名的流程引擎相比,但是在某些場景正勒,的確提供了輕量級(jí)的解決方案罢吃。并且Liteflow經(jīng)過了公司生產(chǎn)大流量業(yè)務(wù)的考驗(yàn),在穩(wěn)定性和性能方面有一定保障昭齐。希望Liteflow這個(gè)開源框架能幫助到有這方面業(yè)務(wù)需要的同學(xué)們尿招。
關(guān)于我
我是一個(gè)開源作者,也是一名內(nèi)容創(chuàng)作者阱驾【兔眨「元人部落」是一個(gè)堅(jiān)持做原創(chuàng)的技術(shù)科技分享號(hào),會(huì)一直分享原創(chuàng)的技術(shù)文章里覆,陪你一起成長丧荐。關(guān)注回復(fù)liteflow
能加入群聊,這里有很多大佬能和你一起探討技術(shù)喧枷,回答你的問題虹统。