最新要闻
- 微头条丨校长用张颂文成名故事激励学生:日复一日打磨自己才是人生征程
- 2022年中国汽车销量排名:上汽第一 比亚迪增速太猛
- 当前头条:真维斯官方清仓:连帽夹克69.9元、棒球服夹克89.9元
- 当前热讯:Switch超级大作 《塞尔达传说:王国之泪》泄露:极具魅力
- 天天快消息!腾讯开办职业技能培训学校 网友:教打游戏吗?
- yy直播是个什么样的平台?YY礼包怎么领取?
- 社稷的原意是指什么?社稷中的社和稷是什么意思?
- 中国五大淡水湖是哪五个?中国五大淡水湖从大到小排列
- 上海世博会的吉祥物叫什么名字?上海世博会的意义有哪些?
- 卢知宣是哪个组合的歌手?卢知宣个人资料
- 世界热推荐:佳能一口气推四款新品:EOS R8、EOS R50都来了
- 爽口弹牙 喜得佳潮汕牛肉丸/牛筋丸19.9元/斤官方大促
- 今年以来最大震级!土耳其7.8级地震现场实拍:房屋倒塌满街狼藉
- 环球观天下!浙大美女老师火了 曾是羽毛球冠军 选课人数远超班级容量
- 环球今热点:旧手机被换菜刀女子开80公里赎回 内含资料太珍贵:型号是小米
- 200M内存就能用 Win11极限精简版实测:C盘只需8GB空间
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
天天微头条丨drools规则动态化实践
作者:京东物流 李振 康睿 刘斌 王北永
一 、 规则引擎业务应用背景
业务逻辑中经常会有一些冗长的判断,需要写特别多的if else,或者一些判断逻辑需要经常修改。这部分逻辑如果以java代码来实现,会面临代码规模控制不住,经常需要修改逻辑上线等多个弊端。这时候我们就需要集成规则引擎对这些判断进行线上化的管理
(资料图片仅供参考)
二、规则引擎选型
目前开源的规则引擎也比较多,根据原有项目依赖以及短暂接触过的规则引擎,我们着重了解了一下几个
drools:
-社区活跃,持续更新
-使用广泛
-复杂
-学习成本较高
https://github.com/kiegroup/drools
easy-rule:
-简单易学
-满足使用诉求
-长时间未发布新版
https://github.com/j-easy/easy-rules
easycode:
-京东物流同事维护的平台
-基于flowable dmn实现
-配置简单直观
-已有大量系统使用
总结:
- 简单配置型规则可以接入easycode,平台提供配置页面,通过jsf交互。
- 复杂规则,需要动态生成规则,easycode目前还不支持。drools从流行度及活跃度考虑,都比easy-rule强,所以选择drools。
三、 drools简单示例
3.1 引入依赖
org.kie kie-spring ${drools.version}
3.2 写drl文件
我们写一个简单的demo
规则为:
匹配一个sku对象
0<价格<=100 10积分
100<价格<=1000 100积分
1000<价格<=10000 1000积分
在resources文件夹下新增 rules/skupoints.drl 文件 内容如下
package com.example.droolsDemoimport com.example.droolsDemo.bean.Sku;// 10积分rule "10_points" when $p : Sku( price > 0 && price <= 100 ) then $p.setPoints(10); System.out.println("Rule name is [" + drools.getRule().getName() + "]");end// 100积分rule "100_points" when $p : Sku( price > 100 && price <= 1000 ) then $p.setPoints(100); System.out.println("Rule name is [" + drools.getRule().getName() + "]");end// 1000积分rule "1000_points" when $p : Sku( price > 1000 && price <= 10000 ) then $p.setPoints(1000); System.out.println("Rule name is [" + drools.getRule().getName() + "]");end
3.3 使用起来
@Test public void testOneSku() { Resource resource = ResourceFactory.newClassPathResource("rules/skupoints.drl"); KieHelper kieHelper = new KieHelper(); kieHelper.addResource(resource); KieBase kieBase = kieHelper.build(); KieSession kieSession = kieBase.newKieSession(); Sku sku1 = new Sku(); sku1.setPrice(10); kieSession.insert(sku1); int allRules = kieSession.fireAllRules(); kieSession.dispose(); System.out.println("sku1:" + JSONObject.toJSONString(sku1)); System.out.println("allRules:" + allRules); } @Test public void testOneSku2() { Resource resource = ResourceFactory.newClassPathResource("rules/skupoints.drl"); KieHelper kieHelper = new KieHelper(); kieHelper.addResource(resource); KieBase kieBase = kieHelper.build(); StatelessKieSession statelessKieSession = kieBase.newStatelessKieSession(); Sku sku1 = new Sku(); sku1.setPrice(10); statelessKieSession.execute(sku1); System.out.println("sku1:" + JSONObject.toJSONString(sku1)); }
3.4 输出
3.5 总结
如上,我们简单使用drools,仅需要注意drl文件语法。根据drl文件生成规则的工作内存,通过KieSession
或者StatelessKieSession
与工作内存交互。整个流程并不复杂。注意 KieHelper
仅是在演示中简单使用,demo中包含使用bean来管理容器的方式,即便在简单使用场景也不应通过 KieHelper
来重复加载规则。
但是,这样并不能满足我们线上化判断,或者频繁更改规则的诉求。于是我们在实践中需要对drools更高阶的使用方式。
四、 drools动态化实践
从以上简单demo中我们可以看出,规则依赖drl文件存在。而业务实际使用中,需要动态对规则进行修改,无法直接使用drl文件。
以下是我了解过的四种动态的方案:
- drt文件,创建模板,动态生成drl文件,也是我们目前所用的方式。
- excel文件导入,实际上和模板文件类似,依然无法直接交给业务人员来使用。
- 自己拼装String,动态生成drl文件,网上大多数博文使用方式,过于原始。
- api方式,drools的api方式复杂,使用需要对drl文件有足够的了解。
最后介绍以下drools在项目中的实际使用方式
4.1 配置规则
我们的业务场景可以理解为多个缓冲池构成的一个网状结构。
示例如下:
上图中每个方块为一个缓冲池,每条连线为一条从A缓冲池流向B缓冲池的规则。实际场景中缓冲池有数百个,绝大多数都有自己的规则,这些规则构成一张复杂的网络。基于业务诉求,缓冲池的流向规则需要经常变动,我们需要在业务中能动态改变这些连线的条件,或者改变连线。在这种情况下,如果使用静态的drl文件来实现这些规则,需要数百规则文件,维护量大,且每次修改后使规则生效的代价较大。在此背景下,我们尝试drools高阶应用,既规则动态化实践。
我们在创建缓冲池的页面中加入了流向规则的创建环节。每个缓冲池维护自己的流向规则,即为自己的一根连线。如下图:
4.2 动态生成drl
drt文件内容:
(实际业务模板中比这个复杂,有一定校验及业务逻辑,此处做了简化)
template header// 模板需要使用的参数idcluePoolIdsourceListcooperateTypeListregionIdsecondDepartmentIdbattleIdoutCluePoolIdamountCompareFlagamountsaliencepackage rulePoolOut// 全局对象global java.util.List list;global java.util.List stopIdList;global java.util.List ruleIdList;// 引入的java类import com.example.drools.bean.ClueModelimport org.springframework.util.CollectionUtilsimport org.apache.commons.lang3.StringUtils;import java.lang.Longtemplate "CluePoolOut"// 规则名称rule "clue_pool_@{cluePoolId}_@{id}"// 参数 标识当前的规则是否不允许多次循环执行no-loop true// 参数 优先级salience @{salience}// 参数 规则组 本组规则只能有一个生效 activation-group "out_@{cluePoolId}"// 匹配的LHSwhen $clue:ClueModel(cluePoolId == @{cluePoolId}) ClueModel(CollectionUtils.isEmpty(@{sourceList}) || source memberOf @{sourceList}) ClueModel(CollectionUtils.isEmpty(@{cooperateTypeList}) || cooperateType memberOf @{cooperateTypeList}) ClueModel(secondDepart == @{secondDepartmentId}) ClueModel(regionNo == @{regionId}) ClueModel(battleId == @{battleId}) ClueModel(null != estimateOrderCount && (Long.valueOf(estimateOrderCount) @{amountCompareFlag} Long.valueOf(@{amount})))// 如果配置要执行的RHS 支持java语法then ruleIdList.add(@{id}); $clue.setCluePoolId(Long.valueOf(@{outCluePoolId})); list.add(@{outCluePoolId}); update($clue); }endend template
生成drl内容: 根据一个队列及模板的路径进行drl内容的生成
List ruleCenterVOS = new ArrayList<>();CrmCluePoolDistributeRuleBusinessBattleVO vo = new CrmCluePoolDistributeRuleBusinessBattleVO();vo.setCooperateTypeList(Lists.newArrayList(1, 2, 4));vo.setAmountCompareFlag(">");vo.setAmount(100L);ruleCenterVOS.add(vo);String drl = droolsManager.createDrlByTemplate(ruleCenterVOS, "rules/CluePoolOutRuleTemplate.drt"); public String createDrlByTemplate(Collection> objects, String path) { ObjectDataCompiler compiler = new ObjectDataCompiler(); try (InputStream dis = ResourceFactory.newClassPathResource(path, this.getClass()).getInputStream()) { return compiler.compile(objects, dis); } catch (IOException e) { log.error("创建drl文件失败!", e); } return null; }
4.3 加载drl
上边的简单示例中,我们使用了KieHelper
来加载规则文件至工作内存中。实际上我们不可能在每次匹配中重新加载所有规则文件,所以我们可以单例的使用规则容器,通过以下方式或者也可以使用@Bean
等方式来管理容器。
private final KieServices kieServices = KieServices.get();// kie文件系统,需要缓存,如果每次添加规则都是重新new一个的话,则可能出现问题。即之前加到文件系统中的规则没有了private final KieFileSystem kieFileSystem = kieServices.newKieFileSystem();// 需要全局唯一一个private KieContainer kieContainer;
通过将内容写入 kieFileSystem
然后重新加载整个 kieBase
即可重新加载规则,但是这种行为比较重,代价较大
也可以通过 kieBase
新增一个文件来进行加载,代价小,但是同步各个实例的代价较大。
KnowledgeBaseImpl kieBase = (KnowledgeBaseImpl)kieContainer.getKieBase(kieBaseName);KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();Resource resource = ResourceFactory.newReaderResource(new StringReader(ruleContent));builder.add(resource,ResourceType.DRL);if (builder.hasErrors()) { throw new RuntimeException("增加规则失败!" + builder.getErrors().toString());}kieBase.addPackages(builder.getKnowledgePackages());
4.4 匹配
通过 StatelessKieSession
与规则引擎交互
// 获取一个链接StatelessKieSession kieSession = droolsManager.getStatelessKieSession(RuleTemplateEnum.CLUE_POOL_OUT_RULE.getKieBaseName());// 创建全局变量对象List list = new ArrayList<>();List stopIdList = Lists.newArrayList();List result = new ArrayList<>();List ruleIdList = new ArrayList<>();// 塞入全局变量kieSession.setGlobal("ruleIdList", ruleIdList);kieSession.setGlobal("list", list);kieSession.setGlobal("stopIdList", stopIdList);kieSession.setGlobal("result", result);// 执行规则kieSession.execute(clueModel);
如果使用 KieSession
则需要在使用完成后进行关闭
kieSession.insert(clueModel);kieSession.fireAllRules();kieSession.dispose();
在执行规则的过程中可以加入各种监听器对过程中各种变化进行监听。篇幅原因交给各位去探索。
五、 总结
从上边的流程中我们体验了动态规则的创建以及使用。动态规则满足了我们规则动态变化,规则统一管理的诉求。
我也总结了在这种使用方式下drools的几个优缺点。
优点:
- 规则动态化方便
- 在工作内存中匹配规则性能好
- 几乎可以满足所有的规则需求
- 内置方法丰富完善
缺点:
- 分布式一致性需要自行处理
- 需要研发了解drl语法
- 学习曲线陡峭
- 匹配过程监控手段需要自行实现
-
全球微动态丨idea引入外部maven项目(非压缩)方式
1、idea版本:2020 032、maven项目:springboot项目或cloud项目3、引入步骤:File->New->ProjectfromExisti
来源: -
每日消息!Hugging News #0203: 3.3 MB 的文生图模型、RHLF 训练框架、手机上能跑的 Transformer
每一周,我们的同事都会向社区的成员们发布一些关于HuggingFace相关的更新,包括我们的产品和平台更新、...
来源: 天天微头条丨drools规则动态化实践
全球微动态丨idea引入外部maven项目(非压缩)方式
每日消息!Hugging News #0203: 3.3 MB 的文生图模型、RHLF 训练框架、手机上能跑的 Transformer
环球今日讯!跟着廖雪峰学python004
微头条丨校长用张颂文成名故事激励学生:日复一日打磨自己才是人生征程
2022年中国汽车销量排名:上汽第一 比亚迪增速太猛
当前头条:真维斯官方清仓:连帽夹克69.9元、棒球服夹克89.9元
当前热讯:Switch超级大作 《塞尔达传说:王国之泪》泄露:极具魅力
天天快消息!腾讯开办职业技能培训学校 网友:教打游戏吗?
显卡花屏一般是什么部件坏了?显卡花屏怎么解决?
gmail账号怎么注册?gmail账号停用怎么快速恢复使用?
libs是什么文件夹?libs文件夹可以删除吗?
win7如何共享打印机?win7怎么设置屏幕不休眠?
显卡风扇不转是什么原因?显卡风扇不转怎么解决?
yy直播是个什么样的平台?YY礼包怎么领取?
社稷的原意是指什么?社稷中的社和稷是什么意思?
世界百事通!Buu刷题
今头条!node中的fs模块和http模块的学习
世界观天下!项目实战:Qt终端命令模拟工具 v1.0.0(实时获取命令行输出,执行指令,模拟ctrl+c中止操作)
环球看热讯:C#判断IP地址是否正确
中国五大淡水湖是哪五个?中国五大淡水湖从大到小排列
上海世博会的吉祥物叫什么名字?上海世博会的意义有哪些?
卢知宣是哪个组合的歌手?卢知宣个人资料
世界热推荐:佳能一口气推四款新品:EOS R8、EOS R50都来了
爽口弹牙 喜得佳潮汕牛肉丸/牛筋丸19.9元/斤官方大促
今年以来最大震级!土耳其7.8级地震现场实拍:房屋倒塌满街狼藉
环球观天下!浙大美女老师火了 曾是羽毛球冠军 选课人数远超班级容量
环球今热点:旧手机被换菜刀女子开80公里赎回 内含资料太珍贵:型号是小米
NutUI 4.0 正式发布!
200M内存就能用 Win11极限精简版实测:C盘只需8GB空间
手机预装App无法卸载是对用户侵害!人大教授:侵犯消费者自主选择权
焦点速讯:男子礁石上钓鱼被海浪拍进石缝 出海垂钓别选偏僻海域
特斯拉辅助驾驶不“看路” 撞碎一地护栏!车主:跟平时不一样
6999元 惠普新款32寸4K显示器上架:配备雷电4 100W供电
俄罗斯杀毒软件卡巴斯基将推自研OS及应用商店:不兼容第三方系统
全球热议:要钱没用!比尔盖茨喊话马斯克做慈善家:我们财富都捐出去
中国游客抛弃日韩后!新西兰首发团26000元1分钟售罄:出境游全面开启
读Java实战(第二版)笔记02_行为参数化Lambda表达式
全球速讯:男子油锅炸元宵现场惨烈 发生自爆崩起半米高:科普为何会翻车
天天头条:中国探月四期全面推进:月球上寻找水源、科研站基本成型
【全球新视野】Intel Arc 750新驱动提升43%游戏性能!RTX 3060最大劲敌来了
【全球播资讯】day02-REST和SpringMVC映射请求数据
万元起步?苹果iPhone 16将推Ultra超旗舰 库克称果粉愿意花高价
存储卡/U盘提示要格式化?先恢复出数据再说
【全球新要闻】2600元的PCIe 5.0 SSD全球首测:读写双破10GB/s!但吵死了
邪恶、丑陋的互联网:你还敢发孩子的短视频吗?
记一次selenium爬取p站图片的经历
世界热门:丰田最新表态:纯电车不环保!
焦点短讯!谷歌家也没有余粮了:用旧的服务器不要扔 擦擦还能用2年
环球快看点丨路由架构(一)
每日精选:《三体》电视剧罗辑亮相 网友:袁华 是你吗?
环球快消息!连续两部当主演 《流浪地球3》中或没有吴京:如何复活很关键
全球要闻:web安全基础-文件上传(含部分upload-labs靶场通关)
世界资讯:谈刻意练习 Talking about deliberate pratise
新动态:Linux环境下:程序的链接, 装载和库[动态链接]
【全球新要闻】染发剂致癌吗?几十块和几百块的染发剂 究竟有啥区别?
全球快讯:等等党赚了:《仙剑奇侠传七》宣布将加入XGP服务
环球新动态:Gmail之父:有了ChatGPT 搜索引擎活不过两年 就像干掉黄页电话簿
每日焦点!操作系统篇 ———— 开篇[一]
全球最资讯丨ES6 简介(二)
量子通信网络里程碑 中国科大实现模式匹配量子密钥分发
男子将厕所改造成电竞房 网友:从此再也不怕“膀胱局”了
世界观速讯丨9 文件操作
当前速看:多国反对被无视 日本2030年前排放40万吨核污水入海
今日关注:“最强法务部”名不虚传:任天堂赢得Joy-Con手柄集体诉讼案
热门:iPhone 14系列官方降价引热议 网友:安卓厂商压力山大
【环球时快讯】Java实现动态数组(数据结构与算法)
【全球新要闻】推特创作者将获得广告分成:需要开通蓝V会员才有资格
一加Ace 2正面“全身照”首次亮相:超窄边框双曲屏
当前速看:高中生分班前磕头跪谢班主任:网友看后意见大!老师回应:给每人发了红包
【全球速看料】MAUI新生6.9-控件辅助功能①:动画Animation
集合框架
10 正则表达式应用
《流浪地球2》里的“硬核科技” 中国电信已经用上了
全球报道:超详细--redis在Linux环境搭建主从复制
当前视讯!ChatGPT将英伟达AI GPU变成黄金 后者股价飙升超40%
《狂飙》带火鱼干店 老板:微信加烦了!剧中原来是这一集
焦点报道:为什么 L1 正则化能做特征选择而 L2 正则化不能
Linux环境下:程序的链接, 装载和库[可执行文件的装载]
当前焦点!Edge新版增加内容推荐按钮:打开甚至不用点
今日报丨比亚迪1月销量:汉卖出1.22万辆 宋Plus继续火爆
当前头条:[数据结构] 哈希表 (开放寻址法+拉链法)
天天动态:车主展示特斯拉自动泊车入位 结果翻车:变成“自动撞车”
【天天速看料】价格暴降后特斯拉供不应求 马斯克:准备要涨了
热点评!迁移学习(HDAN)《Heuristic Domain Adaptation》
美团索命一问:一个SQL ,怎么分析加了哪些锁? 含4大场景、8个规则
宝能造车梦破碎:烧了80多亿元的观致 如今沦为法拍车
女孩4万多元的摩托 被男摩友加白糖报废!官方介入
读Java实战(第二版)笔记01_Java的变化
全球即时:柔软顺滑 古今男士平角裤3条到手29.9元
世界视讯!休闲百搭 361° 运动束脚裤立减140元:49元起清仓价
环球速看:冰火两重天!四川一地昼夜温差38.6℃ 专家揭秘真相
今年开播有戏 “陈萍萍”演员吴刚回应《庆余年》第二季:很快了
python的基础知识1
奔驰被曝大砍产品线!19款车型或将淘汰 原因现实
环球视点!马斯克收费比微博狠多了:推特被曝企业“金V”认证付费:每月6770元
焦点热议:3年前旗舰也有份!中国广电剧透:小米10/青春版计划4月推送MIUI 14
《流浪地球2》票房破32亿元 导演谈第3部:原班人马再来一遍
全球最资讯丨浙江台州最大汽车经销商老板跑路 旗下19家4S店全部关停
12.4万保时捷首单买家发声:保时捷答应优惠卖车