规则引擎LiteFlow发布v2.12.1版本,决策路由特性

个人博客:无奈何杨(wnhyang)

个人语雀:wnhyang

共享语雀:在线知识共享

Github:wnhyang - Overview


简介

标题其实是不准确的,了解过的会知道在LiteFlow2.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版本加入了路由特性,新增了routebody标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<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的方法。

1
List<LiteflowResponse> responseList = flowExecutor.executeRouteChain(requestData, YourContext.class);

在此版本中存在一个很大的问题,或者说是不便。

此方法会执行所有的路由chain,那么所有的路由chain就被限制住了。

举个例子,如果业务需要如下这样决策流程,数据接入后想利用决策路由的特性确定跑哪个策略集,到这里决策路由还是很有用的,但是策略集下其实还有很多规则的,进入策略集后应该还要继续进行决策路由,并行跑所有规则。那么这里就出问题了,因为策略集路由明显和规则路由不是一个概念,而且还不能同时跑,是要策略路由跑完后再进行规则路由的。

image

LiteFlow2.12.1版本,加入了路由分组管理。

1
2
3
4
5
6
7
8
<chain name="chain1" namespace="n1">
<route>
AND(r1, r2, r3)
</route>
<body>
THEN(a, b, c);
</body>
</chain>

同时加入执行分组的方法,很好的解决了此问题。

1
List<LiteflowResponse> responseList = flowExecutor.executeRouteChain("n1", requestData, YourContext.class);

但是

就那上面这张图举例子,步骤有:

1、数据接入

2、判断要执行哪个策略集(唯一)

3、判断要执行策略下的哪些规则(多个)

原先判断要执行哪个策略集需要硬编码确认,有了决策路由就可以配置好route,每个策略集route分配好唯一的namespace,如:每个策略集namespace命名可以是ss-${appName}-${strategySetCode}ssstrategySet的简写,标识namespace属于策略集,唯一性由${appName}-${strategySetCode}动态决定。判断要执行策略下哪些规则的namespace可以命名为rule-${strategyId}rule代表规则路由,后面拼上策略id用于确认规则在哪个策略下,这样确认策略后就可以并行多个执行了。

但写着写着发现还有一个问题,当前决策路由执行好像只有这个方法,没有提供隐式子流程调用,也就说现在执行多个路由只能在不同的流程内,策略集流程执行后如果要执行规则流程的话,只能另行执行路由,两个流程独立开了,这样对我来讲其实是不对的,因为它们是公用上下文的,在同一流程内很有必要。

这个只能暂时期待住了,好像确实没有好的办法,有个方法是上下文复制传下去,但这又和LiteFlow组件化,上下文的思想违背了,和普通的瀑布流程好像又是一样的了,而且将两个流程割裂了,不太好。

1
flowExecutor.executeRouteChain("n1", requestData, YourContext.class);

上下文参数注入

上下文是LiteFlow中一个非常重要的概念,详细请查看官网🍄说明 | LiteFlow

上下文参数注入之适用于声明式组件,声明式组件请看官网🥭什么叫声明式组件 | LiteFlow

哈哈哈,全是看官网。。。

示例

在过去,没有上下文参数注入时,通过声明式组件获取上下文是这样的。

1
2
3
4
5
6
7
8
9
10
@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);

...

}

而有了上下文参数注入特性后就可简化,如下。

1
2
3
4
5
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "accessIn", nodeType = NodeTypeEnum.COMMON)
public void accessIn(NodeComponent bindCmp, @LiteflowFact("params") Map<String, String> params) {
log.info("入参:{}", params);

}

@LiteflowFact中写的表达式,会自动的从上下文中搜索相应的参数。即使你有多个上下文,也无需去指定上下文。

但是有一种情况,在使用时要注意:假设你有两个上下文,TestContext1TestContext2,在这两个上下文里都有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