本文主要介紹 ice 的核心編排思想,并與常見編排思想 (如 Drools/Activity 等) 做了比較。
背景介紹
業務中是否寫了大量的 if-else?是否受夠了這些 if-else 還要經常變動?業務中是否做了大量抽象,發現新的業務場景還是用不上?是否各種調研規則引擎,發現不是太重就是接入或維護太麻煩,最后發現還是不如硬編碼?接下來給大家介紹一款全新的開源規則引擎 ——ice,以一個簡單的例子,從最底層的編排思想,闡述 ice 與其他規則引擎的不同;講述 ice 是如何使用全新的設計思想,契合解耦和復用的屬性,還你最大的編排自由度。規則引擎的應用場景規則引擎在很多業務場景中都有應用,例如:會員營銷:由多種條件、流程、獎勵組合而成,時間線復雜,代碼復用率不高,調整頻繁風控規則:由多種條件組合并返回決策,條件量大且復雜,變動頻繁數據分析:將數據通過分析師自己編排的規則產出想要的數據,千人千面以上場景往往都存在一些共同痛點:靈活業務(變動頻繁,時效性明顯,測試邏輯復雜)追求靈活花里胡哨:產品和運營一直在探索新鮮玩法,導致很多抽象出來的模塊往往扛不過兩個迭代。今天上線又要調整:因為一些偶發情況,如線上用戶參與度不高,及時調整用戶參與門檻等(當然也可以在開發前把所有情況考慮到位,但是為了小概率事件做大量的工作,成本過高)。研發測試心力交瘁:研發硬編碼,測試驗證復雜重復邏輯,久而久之變的愈發疲憊。時間線(多條時間線交織混亂)研發編排錯了再來:一般營銷類型的會涉及很多時間線,而在當前,測試一個未來要上線的具有不同時間節點屬性的活動,硬編碼時往往由研發編排時間,測試進行測試,但是當 bug 發生并打亂時間線時,就需要重新編排時間(沒有經歷過的不用太了解,后面會說)。測試并行孔融讓梨:當時間線發生沖突并有多個測試在沖突位置上并發測試,往往由測試自行協調測試順序,當一方出現問題往往導致后續測試進度不可控。其他問題依賴掛了難以為繼:測試環境為非穩定環境,一旦依賴出了問題難免影響進度,如何能做到簡單高效 mock?修復數據苦不堪言:當線上問題產生時,受影響的客戶如何快速高效的補償?
ice 的設計思想
為了方便理解,設計思路將伴隨著一個簡單的充值例子展開。
舉例
X 公司將在國慶放假期間,開展一個為期七天的充值小活動,活動內容如下:活動時間:(10.1-10.7)活動內容:充值 100 元 送 5 元余額 (10.1-10.7)充值 50 元 送 10 積分 (10.5-10.7)活動備注: 不疊加送 (充值 100 元只能獲得 5 元余額,不會疊加贈送 10 積分)簡單拆解一下,想要完成這個活動,我們需要開發如下模塊:
如上圖,當用戶充值成功后,會產生對應充值場景的參數包裹 Pack (類 Activiti/Drools 的 Fact),包裹里會有充值用戶的 uid,充值金額 cost,充值的時間 requestTime 等信息。我們可以通過定義的 key,拿到包裹中的值 (類似 map.get (key))。模塊怎么設計無可厚非,重點要講的是后面的怎么編排實現配置自由,接下來將通過已有的上述節點,講解不同的規則引擎在核心的編排上的優缺點,并比較 ice 是怎么做的。
流程圖式實現
類 Activiti、 Flowable 實現:
流程圖式實現,應該是我們最常想到的編排方式了~看起來非常的簡潔易懂,通過特殊的設計,如去掉一些不必要的線,可以把 UI 做的更簡潔一些。但由于有時間屬性,其實時間也是一個規則條件,加上之后就變成了:
看起來也還好
執行樹式實現
類 Drools 實現 (When X Then Y):
這個看起來也還好,再加上時間線試試:
依舊比較簡潔,至少比較流程圖式,我會比較愿意修改這個。
計劃永遠趕不上變化
上面兩種方案的優點在于,可以把一些零散的配置結合業務很好的管理了起來,對配置的小修小改,都是信手拈來,但是真實的業務場景,可能還是要錘爆你,有了靈活的變動,一切都不一樣了。
理想
不會變的,放心吧,就這樣,上
現實
①充值 100 元改成 80 吧,10 積分變 20 積分吧,時間改成 10.8 號結束吧(微微一笑,畢竟我費了這么大勁搞規則引擎,終于體現到價值了!)②用戶參與積極性不高啊,去掉不疊加送吧,都送(稍加思索,費幾個腦細胞挪一挪還是可以的,怎么也比改代碼再上線強吧!)③5 元余額不能送太多,設置個庫存 100 個吧,對了,庫存不足了充 100 元還是得送 10 積分的哈(卒… 早知道還不如硬編碼了)以上變動其實并非看起來不切實際,畢竟真實線上變動比這離譜的多的是,流程圖式和執行樹式實現的主要缺點在于,牽一發而動全身,改動一個節點需要瞻前顧后,如果考慮不到位,很容易弄錯,而且這還只是一個簡單的例子,現實的活動內容要比這復雜的多的多,時間線也是很多條,考慮到這,再加上使用學習框架的成本,往往得不償失,到頭來發現還不如硬編碼。怎么辦?
讓我們看看 ice 是怎么做的?
引入關系節點
關系節點為了控制業務流轉AND所有子節點中,有一個返回 false 該節點也將是 false,全部是 true 才是 true,在執行到 false 的地方終止執行,類似于 Java 的 &&ANY所有子節點中,有一個返回 true 該節點也將是 true,全部 false 則 false,在執行到 true 的地方終止執行,類似于 Java 的 ||ALL所有子節點都會執行,有任意一個返回 true 該節點也是 true,沒有 true 有一個節點是 false 則 false,沒有 true 也沒有 false 則返回 none,所有子節點執行完畢終止NONE所有子節點都會執行,無論子節點返回什么,都返回 noneTRUE所有子節點都會執行,無論子節點返回什么,都返回 true,沒有子節點也返回 true (其他沒有子節點返回 none)
引入葉子節點
葉子節點為真正處理的節點Flow一些條件與規則節點,如例子中的 ScoreFlowResult一些結果性質的節點,如例子中的 AmountResult,PointResultNone一些不干預流程的動作,如裝配工作等,如下文會介紹到的 TimeChangeNone有了以上節點,我們要怎么組裝呢?
如上圖,使用樹形結構 (對傳統樹做了鏡像和旋轉),執行順序還是類似于中序遍歷,從 root 執行,root 是個關系節點,從上到下執行子節點,若用戶充值金額是 70 元,執行流程:[ScoreFlow-100:false]→[AND:false]→[ScoreFlow-50:true]→[PointResult:true]→[AND:true]→[ANY:true]這個時候可以看到,之前需要剝離出的時間,已經可以融合到各個節點上了,把時間配置還給節點,如果沒到執行時間,如發放積分的節點 10.5 日之后才生效,那么在 10.5 之前,可以理解為這個節點不存在。
變化的靈活快速應對
對于①直接修改節點配置就可以對于②直接把 root 節點的 ANY 改成 ALL 就可以 (疊加送與不疊加送的邏輯在這個節點上,屬于這個節點的邏輯就該由這個節點去解決)對于③由于庫存的不足,相當于沒有給用戶發放,則 AmountResult 返回 false,流程還會繼續向下執行,不用做任何更改再加一個棘手的問題,當時間線復雜時,測試工作以及測試并發要怎么做?一個 10.1 開始的活動,一定是在 10.1 之前開發上線完畢,比如我在 9.15 要怎么去測試一個 10.1 開始的活動?在 ice 中,只需要稍微修改一下:
如圖,引入一個負責更改時間的節點 TimeChangeNone (更改包裹中的 requestTime),后面的節點執行都是依賴于包裹中的時間即可,TimeChangeNone 類似于一個改時間的插件一樣,如果測試并行,那就給多個測試每人在自己負責的業務上加上改時間插件即可。
ice 的特性
為什么這么拆解呢?為什么這樣就能解決這些變動與問題呢?其實,就是使用樹形結構解耦,流程圖式和執行樹式實現在改動邏輯的時候,不免需要瞻前顧后,但是 ice 不需要,ice 的業務邏輯都在本節點上,每一個節點都可以代表單一邏輯,比如我改不疊加送變成疊加送這一邏輯就只限制在那個 ANY 節點邏輯上,只要把它改成我想要的邏輯即可,至于子節點有哪些,不用特別在意,節點之間依賴包裹流轉,每個節點執行完的后續流程不需要自己指定。因為自己執行完后的執行流程不再由自己掌控,就可以做到復用:
如圖,參與活動這里用到的 TimeChangeNone,如果現在還有個 H5 頁面需要做呈現,不同的呈現也與時間相關,怎么辦?只需要在呈現活動這里使用同一個實例,更改其中一個,另一個也會被更新,避免了到處改時間的問題。同理,如果線上出了問題,比如 sendAmount 接口掛了,由于是 error 不會反回 false 繼續執行,而是提供了可選策略,比如將 Pack 以及執行到了哪個節點落盤起來,等到接口修復,再繼續丟進 ice 重新跑即可 (由于落盤時間是發生問題時間,完全不用擔心活動結束了的修復不生效問題),同樣的,如果是不關鍵的業務如頭像服務掛了,但是依然希望跑起來,只是沒有頭像而已,這樣可以選擇跳過錯誤繼續執行。這里的落盤等規則不細展開描述。同樣的原理也可以用在 mock 上,只需要在 Pack 中增加需要 mock 的數據,就可以跑起來。
引入前置節點
上面的邏輯中可以看到有一些 AND 節點緊密綁定的關系,為了視圖與配置簡化,增加了前置 (forward) 節點概念,當且僅當前置節點執行結果為非 false 時才會執行本節點,語義與 AND 相連的兩個節點一致。
-
模塊
+關注
關注
7文章
2718瀏覽量
47555 -
編碼
+關注
關注
6文章
946瀏覽量
54869 -
開源
+關注
關注
3文章
3368瀏覽量
42567 -
數據分析
+關注
關注
2文章
1452瀏覽量
34076
原文標題:開源規則引擎-ice(致力于解決靈活繁復的硬編碼問題)
文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論