Spring Boot + liteflow 規(guī)則引擎,太香了!
在日常的開發(fā)過程中,經(jīng)常會(huì)遇到一些串行或者并行的業(yè)務(wù)流程問題,而業(yè)務(wù)之間不必存在相關(guān)性。
在這樣的場(chǎng)景下,使用策略和模板模式的結(jié)合可以很好的解決這個(gè)問題,但是使用編碼的方式會(huì)使得文件太多,在業(yè)務(wù)的部分環(huán)節(jié)可以這樣操作,在項(xiàng)目角度就無法一眼洞穿其中的環(huán)節(jié)和邏輯。
在本文中,將引入規(guī)則引擎從全局角度來解決這個(gè)問題,這就是今天要介紹的主角 liteflow。
1. liteflow 規(guī)則引擎
liteflow 是一個(gè)輕巧而且強(qiáng)大的規(guī)則引擎,能夠?qū)崿F(xiàn)開箱即用,可以在短時(shí)間內(nèi)就可以完成復(fù)雜的規(guī)則編排,下圖是 liteflow 的整體架構(gòu)。liteflow 支持較多的規(guī)則文件格式,比如 xml/json/yaml, 對(duì)于規(guī)則文件的存儲(chǔ)方式可以有sql/zk/nacos/apollo 等。
圖片
liteflow 的使用是從獲取上下文開始的,通過數(shù)據(jù)上下文來解析對(duì)應(yīng)的規(guī)則文件,通過 liteflow 執(zhí)行器來執(zhí)行對(duì)應(yīng)的鏈路,每個(gè)鏈路上都有需要執(zhí)行的業(yè)務(wù) node(即節(jié)點(diǎn)組件,可以支持多種語言腳本, groovy/js/python/lua等), 各個(gè)業(yè)務(wù)node 之間是獨(dú)立的。liteflow 對(duì)應(yīng)的官方網(wǎng)址和依賴如下所示:
liteflow 規(guī)則引擎官方網(wǎng)址
- https://liteflow.yomahub.com
 
<dependency>
    <groupId>com.yomahub</groupId>
    <artifactId>liteflow-spring-boot-starter</artifactId>
    <version>2.10.6</version>
</dependency>liteflow 可以支持如下所示的復(fù)雜流程
圖片
此外,liteflow 可以支持熱部署,可以實(shí)時(shí)替換或者增加節(jié)點(diǎn),即修改規(guī)則文件后可以實(shí)時(shí)生效。
圖片
2. liteflow 的使用方法
2.1 組件
liteflow 的組件在規(guī)則文件中即對(duì)應(yīng)的節(jié)點(diǎn),組件對(duì)應(yīng)的種類有很多,具體的如下所示:
- 普通組件
 
普通組件需要集成的是 NodeComponent, 可以用在 when 和 then 邏輯中,具體的業(yè)務(wù)需要在 process 中去執(zhí)行。同時(shí)在 node 節(jié)點(diǎn)中,可以覆蓋 iaAccess 方法,表示是否進(jìn)入該節(jié)點(diǎn)執(zhí)行業(yè)務(wù)邏輯,isContinueOnError 判斷在出錯(cuò)的情況下是否繼續(xù)執(zhí)行下一個(gè)組件,默認(rèn)為 false。isEnd 方法表示是否終止流程,默認(rèn)為true。
- 選擇組件
 
選擇組件是通過業(yè)務(wù)邏輯來判斷接下來的動(dòng)作要執(zhí)行哪一個(gè)節(jié)點(diǎn),類似于 Java中的 switch , 在代碼中則需要繼承 NodeSwitchComponent 實(shí)現(xiàn) processWitch 方法來處理業(yè)務(wù)。
# flow 規(guī)則表達(dá)式 選擇組件
SWITCH(a).to(b, c);
# processWitch 表達(dá)式需要返回的是 b 或者 c 字符串來執(zhí)行相應(yīng)的業(yè)務(wù)邏輯
# flow 規(guī)則表達(dá)式 條件組件
IF(x, a, b);- 條件組件
 
條件組件稱之為 if 組件,返回的結(jié)果是 true 或者 false, 代碼需要集成 NodeIfComponent 重寫 processIf 方法,返回對(duì)應(yīng)的業(yè)務(wù)節(jié)點(diǎn),這個(gè)和選擇組件類似。
在官方文檔中,還有次數(shù)循環(huán)組件,條件循環(huán)組件,循環(huán)迭代組件,和退出循環(huán)組件,作者認(rèn)為其應(yīng)用場(chǎng)景比較復(fù)雜,可以使用簡(jiǎn)單的普通組件來替代,畢竟是輕量級(jí)的規(guī)則引擎,主要作用就是為了編排流程順序,復(fù)雜的場(chǎng)景就升級(jí)使用工作流了,所以這里只介紹以上三種組件。
2.2 EL 規(guī)則文件
規(guī)則文件的編寫和組件的使用是對(duì)應(yīng)的,這里使用xml 的形式來編寫。
# 文件編排, then 代表串行執(zhí)行  when 表示并行執(zhí)行
# 串行編排示例
THEN(a, b, c, d);
# 并行編排示例
WHEN(a, b, c);
# 串行和并行嵌套結(jié)合
THEN( a, WHEN(b, c, d), e);
# 選擇編排示例
SWITCH(a).to(b, c, d);
# 條件編排示例
THEN(IF(x, a),b );2.3 數(shù)據(jù)上下文
在 liteflow 中,數(shù)據(jù)上下文的概念非常重要,上下文對(duì)象起到參數(shù)傳遞的作用,因?yàn)椴煌瑯I(yè)務(wù)需要的輸入輸出參數(shù)是不同的,所以上下文非常的重要。
# 執(zhí)行流程時(shí),需要傳遞el文件,初始化參數(shù)以及上下文對(duì)象,這里的上下文可以設(shè)置多個(gè)
LiteflowResponse response = flowExecutor.execute2Resp("chain1", 流程初始參數(shù), CustomContext.class);因?yàn)樯舷挛膫魅氲氖且粋€(gè) class 類型參數(shù),流程參數(shù)是可以傳入?yún)?shù)的,一般情況下是在第一個(gè)節(jié)點(diǎn)中,將傳入?yún)?shù)設(shè)置到上下文對(duì)象中。
2.4 參數(shù)配置
在 liteflow 中,需要配置的內(nèi)容有規(guī)則文件地址,節(jié)點(diǎn)重試(執(zhí)行報(bào)錯(cuò)時(shí)可以進(jìn)行重試,類似于 spring-retry), 流程并行執(zhí)行線程池參數(shù)配置,流程的請(qǐng)求ID配置。
liteflow:
  # 規(guī)則文件 失敗重試次數(shù) 打印執(zhí)行日志 監(jiān)控日志
ruleSource :liteflow/*.el.xml
retry-count:0
print-execution-log:true
monitor:
    enable-log:true
    period:300000
request-id-generator-class:com.platform.orderserver.config.AppRequestIdGenerator
# 上下文的最大數(shù)量槽
slot-size :10240
# 線程數(shù),默認(rèn)為64
main-executor-works:64
# 異步線程最長(zhǎng)等待時(shí)間 秒
when-max-wait-seconds:15
# when 節(jié)點(diǎn)全局異步線程池最大線程數(shù)
when-max-workers:16
# when 節(jié)點(diǎn)全局異步線程池隊(duì)列數(shù)
when-queue-limit:5120
# 在啟動(dòng)的時(shí)候就解析規(guī)則
parse-on-start:true
enable:true3. 業(yè)務(wù)實(shí)踐
之前介紹了 liteflow 的一些概念,在這里結(jié)合一些業(yè)務(wù)場(chǎng)景來進(jìn)行演示:
主要使用電商場(chǎng)景的應(yīng)用,訂單完成后,進(jìn)行積分的發(fā)放,消息發(fā)送,同時(shí)并行發(fā)送短信和郵件。
<?xml versinotallow="1.0" encoding="UTF-8"?>
<flow>
    <chain name="test_flow">
        THEN(
           prepareTrade, grantScore, sendMq, WHEN(sendEmail, sendPhone)
        );
    </chain>
</flow>在訂單完成之后異步執(zhí)行,傳遞參數(shù)并執(zhí)行相應(yīng)的規(guī)則流程。
圖片
在正式處理業(yè)務(wù)流程之前,需要先進(jìn)行數(shù)據(jù)的預(yù)處理,將流程入?yún)⑥D(zhuǎn)轉(zhuǎn)換成上下文對(duì)象,方便參數(shù)的傳遞和設(shè)置。
圖片
在具體的業(yè)務(wù)處理環(huán)節(jié),以積分發(fā)放為例,可以獲取上下文對(duì)象進(jìn)行業(yè)務(wù)操作,同時(shí)也可以重寫 isAccess 方法,來判斷是否處理該節(jié)點(diǎn)。
圖片
如上圖所示,具體的業(yè)務(wù)流程都可以抽象成一個(gè) node 節(jié)點(diǎn),存放在 test_flow.el.xml 中進(jìn)行執(zhí)行,其它的代碼都和積分發(fā)放類似,這里就不再贅述,可以參見代碼。
4. 總結(jié)
liteflow 中的絕大部分是在啟動(dòng)時(shí)完成的,包括規(guī)則解析、注冊(cè)組件以及組裝信息,其執(zhí)行性能很高,同時(shí)也可以打印每個(gè)業(yè)務(wù)環(huán)節(jié)的耗時(shí)以及統(tǒng)計(jì)信息。















 
 
 


















 
 
 
 