個人博客:無奈何楊(wnhyang)
個人語雀:wnhyang
共享語雀:在線知識共享
Github:wnhyang - Overview
簡介
標題其實是不準確的,了解過的會知道在LiteFlow
的2.12.0
已經有了決策路由的特性,但我為什么標題這么講呢?且往下看。
因為這篇文章LF的重磅特性預告:決策路由,我一直期待著決策路由功能的發布,終于有一天它發布了!
決策路由特性來襲,LiteFlow大版本2.12.0發布,Make your code amaing!。
雖然這次是大更新,發布的不只是決策路由,但是我心心念念的決策路由并沒有我期待的那樣好用,因為這個版本的路由是全局匹配,沒有分組或分級的概念,在實際使用中并不那么好用。雖然能通過一些代碼來實現類似的分組功能,但是肯定不如框架實現的好,同時也不想因此將代碼來回變動,所以通過社區向作者提意見,正好作者早有此想法,非常nice!
這次規則引擎LiteFlow發布v2.12.1版本,有多猛用過才知道,2.12.1
版本帶來此功能,我也默默的將許久未編輯的《LiteFlow大版本2.12.0發布,決策路由發布》的文章重命名了標題《規則引擎LiteFlow發布v2.12.1版本,決策路由特性》。
參考
🏖概念以及介紹 | LiteFlow
2.12.0升級指南 | LiteFlow
決策路由
說明
關于LiteFlow
,不想再過多介紹了。之前的文章也有說明了風控系統之普通規則條件,使用LiteFlow實現。
非常推薦通過官網來學習,很有幫助!
路由嘛,知道Nginx
吧,可以理解為location
的配置,不知道Nginx
,類比微服務網關也一樣。
在2.12.0
版本加入了路由特性,新增了route
和body
標簽。
<chain name="chain1"><route>AND(r1, r2, r3)</route><body>THEN(a, b, c);</body>
</chain><chain name="chain2"><route>AND(OR(r4, r5), NOT(r3))</route><body>SWITCH(x).TO(d, e, f);</body>
</chain>
同時提供了專門用于執行路由chain
的方法。
List<LiteflowResponse> responseList = flowExecutor.executeRouteChain(requestData, YourContext.class);
在此版本中存在一個很大的問題,或者說是不便。
此方法會執行所有的路由chain
,那么所有的路由chain
就被限制住了。
舉個例子,如果業務需要如下這樣決策流程,數據接入后想利用決策路由的特性確定跑哪個策略集,到這里決策路由還是很有用的,但是策略集下其實還有很多規則的,進入策略集后應該還要繼續進行決策路由,并行跑所有規則。那么這里就出問題了,因為策略集路由明顯和規則路由不是一個概念,而且還不能同時跑,是要策略路由跑完后再進行規則路由的。
在LiteFlow
的2.12.1
版本,加入了路由分組管理。
<chain name="chain1" namespace="n1"><route>AND(r1, r2, r3)</route><body>THEN(a, b, c);</body>
</chain>
同時加入執行分組的方法,很好的解決了此問題。
List<LiteflowResponse> responseList = flowExecutor.executeRouteChain("n1", requestData, YourContext.class);
但是
就那上面這張圖舉例子,步驟有:
1、數據接入
2、判斷要執行哪個策略集(唯一)
3、判斷要執行策略下的哪些規則(多個)
原先判斷要執行哪個策略集需要硬編碼確認,有了決策路由就可以配置好route
,每個策略集route
分配好唯一的namespace
,如:每個策略集namespace
命名可以是ss-${appName}-${strategySetCode}
,ss
是strategySet
的簡寫,標識namespace
屬于策略集,唯一性由${appName}-${strategySetCode}
動態決定。判斷要執行策略下哪些規則的namespace
可以命名為rule-${strategyId}
,rule
代表規則路由,后面拼上策略id用于確認規則在哪個策略下,這樣確認策略后就可以并行多個執行了。
但寫著寫著發現還有一個問題,當前決策路由執行好像只有這個方法,沒有提供隱式子流程調用,也就說現在執行多個路由只能在不同的流程內,策略集流程執行后如果要執行規則流程的話,只能另行執行路由,兩個流程獨立開了,這樣對我來講其實是不對的,因為它們是公用上下文的,在同一流程內很有必要。
這個只能暫時期待住了,好像確實沒有好的辦法,有個方法是上下文復制傳下去,但這又和LiteFlow
組件化,上下文的思想違背了,和普通的瀑布流程好像又是一樣的了,而且將兩個流程割裂了,不太好。
flowExecutor.executeRouteChain("n1", requestData, YourContext.class);
上下文參數注入
上下文是LiteFlow
中一個非常重要的概念,詳細請查看官網🍄說明 | LiteFlow。
上下文參數注入之適用于聲明式組件,聲明式組件請看官網🥭什么叫聲明式組件 | LiteFlow。
哈哈哈,全是看官網。。。
示例
在過去,沒有上下文參數注入時,通過聲明式組件獲取上下文是這樣的。
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "accessIn", nodeType = NodeTypeEnum.COMMON)
public void accessIn(NodeComponent bindCmp) {DecisionRequest decisionRequest = bindCmp.getContextBean(DecisionRequest.class);// 處理入參Map<String, String> params = decisionRequest.getParams();log.info("入參:{}", params);...}
而有了上下文參數注入特性后就可簡化,如下。
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "accessIn", nodeType = NodeTypeEnum.COMMON)
public void accessIn(NodeComponent bindCmp, @LiteflowFact("params") Map<String, String> params) {log.info("入參:{}", params);}
在@LiteflowFact
中寫的表達式,會自動的從上下文中搜索相應的參數。即使你有多個上下文,也無需去指定上下文。
但是有一種情況,在使用時要注意:假設你有兩個上下文,TestContext1
和TestContext2
,在這兩個上下文里都有user
這個對象,并且兩個user
里的信息是不一樣的。這時你通過@LiteflowFact("user") User user
這樣去拿,拿到的是第一個user
,在不同環境上可能還不一樣。
所以使用上下文參數注入特性時,如果有多個上下文,請確保注入的對象,在多個上下文中只有一份,否則會有錯亂情況。
其實它的意義不僅僅是“簡化”,對我來講它其實是解放了聲明式組件,原來在我們編寫了聲明式組件后,他就只是個LiteFlow
組件了,甚至不能做其他事情了。
如上例子public void accessIn(NodeComponent bindCmp)
,方法體中使用到了bindCmp
獲取上下文,并使用這個上下文執行某些流程。這樣的話這個方法就困死在LiteFlow
組件中了,因為我們并沒有這個bindCmp
傳進方法內。而加入了上下文參數注入后,此方法就變為public void accessIn(NodeComponent bindCmp, @LiteflowFact("params") Map<String, String> params)
,看似好像只是加了一個參數,其實也是加了個參數😂但是因為這個參數,間接的解放了此方法,這時我們再調用此方法不用關心bindCmp
了(前提是方法體中沒用到這個),關注@LiteflowFact
修飾的參數即可。
寫在最后
拙作艱辛,字句心血,望諸君垂青,多予支持,不勝感激。
個人博客:無奈何楊(wnhyang)
個人語雀:wnhyang
共享語雀:在線知識共享
Github:wnhyang - Overview