• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

关于java:我们自研的-Ice-规则引擎开源了

java 搞代码 3年前 (2022-01-27) 53次浏览 已收录 0个评论

前言

背景介绍

   规定/流程引擎想必大家并不生疏,耳熟能详的就有Drools,Esper,Activiti,Flowable等,很多大厂也热衷于钻研本人的规定引擎,都是用于解决灵便场景下的简单规定与流程问题,想要做到改改配置就能够生成/失效新的规定,脱离硬编码的苦海。毕竟改改配置和在已有根底上编排规定/流程,比硬编码的成本低很多,然而应用市面上现有的规定引擎来编排,一来接入老本和学习老本都不低,二来随着工夫的推移,规定变的越发宏大以及一些场景的不实用,更加让人叫苦不迭。

「设计思路」

为了不便了解,设计思路将随同着一个简略的充值例子开展。

「举例」

X公司将在国庆放假期间,发展一个为期七天的充值小流动,流动内容如下:

流动工夫:(10.1-10.7)

流动内容:

充值100元 送5元余额(10.1-10.7)

充值50元   送10积分 (10.5-10.7)

流动备注:不叠加送(充值100元只能取得5元余额,不会叠加赠送10积分)

简略拆解一下,想要实现这个流动,咱们须要开发如下模块:

图中发现有待发放key,这个key是从哪里来呢:

如图,当用户充值胜利后,会产生对应充值场景的参数包裹Pack(类Activiti/Drools的Fact),包裹里会有充值用户的uid,充值金额spend,充值的工夫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】

所有子节点都会执行,无论子节点返回什么,都返回none 

【TRUE】

所有子节点都会执行,无论子节点返回什么,都返回true,没有子节点也返回true(其余没有子节点返回none)

「引入叶子节点」

叶子节点为真正解决的节点 【Flow】 一些条件与规定节点,如例子中的ScoreFlow 【Result】 一些后果性质的节点,如例子中的AmountResult,PointResult 【None】 一些不干涉流程的动作,如拆卸工作等,如下文会介绍到的TimeChangeNone 有了以上节点,咱们要怎么组装呢?

如图,应用树形构造(对传统树做了镜像和旋转),执行程序还是相似于中序遍历,从root执行,root是个关系节点,从上到下执行子节点,若用户充值金额是70元,执行流程:

这个时候能够看到,之前须要剥离出的工夫,曾经能够交融到各个节点上了,把工夫配置还给节点,如果没到执行工夫,如发放积分的节点10.5日之后才失效,那么在10.5之前,能够了解为这个节点不存在。

「变动与问题的解决」

对于①间接批改节点配置就能够

对于②间接把root节点的ANY改成ALL就能够(叠加送与不叠加送的逻辑在这个节点上,属于这个节点的逻辑就该由这个节点去解决)

对于③因为库存的有余,相当于没有给用户发放,则AmountResult返回false,流程还会持续向下执行,不必做任何更改

再加一个辣手的问题,当工夫线简单时,测试工作以及测试并发要怎么做?一个10.1开始的流动,肯定是在10.1之前开发上线结束,比方我在9.15要怎么去测试一个10.1开始的流动?在ice中,只须要略微批改一下:

如图,引入一个负责更改工夫的节点TimeChangeNone(更改包裹中的requestTime),前面的节点执行都是依赖于包裹中的工夫即可,TimeChangeNone相似于一个改工夫的插件一样,如果测试并行,那就给多个测试每人在本人负责的业务上加上改工夫插件即可。

「个性」

为什么这么拆解呢?为什么这样就能解决这些变动与问题呢?

其实,就是应用树形构造解耦,流程图式和执行树式实现在改变逻辑的时候,未免须要前怕狼;后怕虎,然而ice不须要,ice的业务逻辑都在本节点上,每一个节点都能够代表繁多逻辑,比方我改不叠加送变成叠加送这一逻辑就只限度在那个ANY节点逻辑上,只有把它改成我想要的逻辑即可,至于子节点有哪些,不必特地在意,节点之间依赖包裹流转,每个节点执行完的后续流程不须要本人指定。

因为本人执行完后的执行流程不再由本人掌控,就能够做到复用:

如图,参加流动这里用到的TimeChangeNone,如果当初还有个H5页面须要做出现,不同的出现也与工夫相干,怎么办?只须要在出现流动这里应用同一个TimeChangeNone实例,更改其中一个,另一个也会被更新,防止了到处改工夫的问题。

同理,如果线上出了问题,比方sendAmount接口挂了,因为是error不会反回false继续执行,而是提供了可选策略,比方将Pack以及执行到了哪个节点落盘起来,等到接口修复,再持续丢进ice从新跑即可(因为落盘工夫是产生问题工夫,齐全不必放心流动完结了的修复不失效问题),同样的,如果是不要害的业务如头像服务挂了,然而仍然心愿跑起来,只是没有头像而已,这样能够抉择跳过谬误继续执行。这里的落盘等规定不细开展形容。同样的原理也能够用在mock上,只须要在Pack中减少须要mock的数据,就能够跑起来。

「引入前置节点」

下面的逻辑中能够看到有一些AND节点严密绑定的关系,为了视图与配置简化,减少了前置(forward)节点概念,当且仅以后置节点执行后果为非false时才会执行本节点,语义与AND相连的两个节点统一。

业余的文档

code

Talk is cheap. Show me the code… 

github: https://github.com/zjn-zjn/ice 

gitee: https://gitee.com/waitmoon/ice 

doc: http://waitmoon.com/docs/#/


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:关于java:我们自研的-Ice-规则引擎开源了

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址