整理了下最近在项目中使用drools出现的问题,幸好都在开发与测试阶段解决了,未波及到prod。

首先看这样两条规则:

/*** 规则1_set默认利率a
 */
rule "rate_default_a"no-loop truewhen$request:AmountRateRequest(calculateEnum == CalculateEnum.INTEREST || calculateEnum == CalculateEnum.AMOUNT_INTEREST)$response:AmountRateResponse(rateMap not contains LoanTermEnum.LOANTERM3)$data:DroolsData()thenDroolsClient.logger.debug("{}执行规则{}", $response.getUserId(), drools.getRule().getName());$response.getRateMap().put(LoanTermEnum.LOANTERM3, RateFactory.DEFAULT_RATE_A);update($response);
end/*** 规则2_set默认利率b*/
rule "rate_default_b"no-loop truewhen$request:AmountRateRequest(calculateEnum == CalculateEnum.INTEREST || calculateEnum == CalculateEnum.AMOUNT_INTEREST)$response:AmountRateResponse(rateMap not contains LoanTermEnum.LOANTERM3)thenDroolsClient.logger.debug("{}执行规则{}", $response.getUserId(), drools.getRule().getName());$response.getRateMap().put(LoanTermEnum.LOANTERM3, RateFactory.DEFAULT_RATE_B);update($response);
end

理想的情况:当规则fire后,rate_default_a规则实行,并set3期利率,得到结果后,由于不满足b规则的when条件(rateMap中3期利率已经存在),则不会继续执行rate_default_b,一切正常,

实际的结果:a执行后触发b、b执行后触发a,造成死循环

原因分析:

  肯定是因为when条件约束失败,导致重复触发,而与规则中修改所相关的就是

$response:AmountRateResponse(rateMap not contains LoanTermEnum.LOANTERM3)

  在drools中,不能通过contains来判断java的map对象是否containsKey。contains 只能用于对象的某个Collection/Array 类型的字段与另外一个值进行比较,作为比较的值可以是一个静态的值,也可以是一个变量(绑定变量或者是一个global 对象),不能操作map。如果需要判断map,建议使用map[keyName]的方式,比如我们这条规则,可以修改为:

$response:AmountRateResponse(rateMap[LoanTermEnum.LOANTERM3] == null)

来做,即可正确判断map的某个值是否为空。

同时对规则中出现的no-loop进行分析:  

  网络中能找到的大部分回答:no-loop属性的作用是用来控制已经执行过的规则在条件再次满足时是否再次执行。默认情况下规则的no-loop属性的值为false,如果no-loop 属性值为true,那么就表示该规则只会被引擎检查一次

  实际效果:no-loop所说的只执行一次,是说当本条规则内如果更新了fact,不会重新触发本条规则的执行。如果像我们上面代码中的情况,a规则和b规则本身都有no-loop true,但a中的udpate仍可以触发b的执行,b也可以触发a。

  如果需要让某条规则只能触发一次,则不能靠no-loop,需要使用lock-on-active true来做。同时注意:虽然规则只能被执行一次是可以做到的,但对于一些场景中,某些规则不希望被触发,并不只是限制次数,还需要结合具体业务来做。

结论和改进:

  1. 不要使用contains操作map,采用map[keyName]的形式

  2. 规则导致的死循环可能有很多种形式,a触发a、ab间相互触发,都可能引起很坏的结果,上线前要谨慎。

  3. 建议在每条规则执行前后增加日志,当出现死循环、或其他不符合预期的结果时能快速定位,方便追踪。

  4. 建议把怀疑有问题的语句拆成最小的单元执行。比如对我们上面的代码稍微修改,只保留一条规则:

/*** 规则1_set默认利率a*/
rule "rate_default_a"no-loop truewhen$request:AmountRateRequest(calculateEnum == CalculateEnum.INTEREST || calculateEnum == CalculateEnum.AMOUNT_INTEREST)$response:AmountRateResponse(rateMap not contains LoanTermEnum.LOANTERM3)$data:DroolsData()thenDroolsClient.logger.debug("{}执行规则{}", $response.getUserId(), drools.getRule().getName());$response.getRateMap().put(LoanTermEnum.LOANTERM3, RateFactory.DEFAULT_RATE_A);update($response);
end

  虽然不会导致死循环,但也无法说明到底是因为contains有效、还是no-loop true不触发自身,具体是哪行导致的结果正常。如果我们去掉no-loop true,就会发现依然出现了死循环,发现是contains的问题。

转载于:https://www.cnblogs.com/loveCheery/p/8544115.html

drools规则引擎中易混淆语法分析_相互触发导致死循环分析相关推荐

  1. Drools规则引擎-memberOf操作

    场景 规则引擎技术讨论2群(715840230)有同学提出疑问,memberOf的使用过程中如果,memberOf之后的参数不是集合也不是数组,而是格式如"1,2,3,4"的字符串 ...

  2. drools规则引擎技术指南_物联网规则引擎技术

    物联网应用程序设计与典型的IT解决方案大不相同,因为它将物理操作技术(OT)与传感器.致动器和通信设备连接起来,并将数字信息技术(IT)与数据.分析和工作流连接起来. 在企业环境中,物联网非常复杂,这 ...

  3. drools规则引擎的在项目中的使用手记

    需求 按照登录用户的会员等级 和签到周期 根据一定的计算规则送积分.由于之前都是通过if else去做的控制.规则变更的时候可能需要重新调整代码甚至发布服务. 由于不想再每次规则变更后需要调整代码,于 ...

  4. drools规则引擎可视化_一文看懂开源工作流引擎 Flowable「转」

    原文链接:[https://xie.infoq.cn/article/ece75889c715e0bc87a73e44c]. 一.工作流引擎使用场景 工作流在企业管理系统中是高频使用的功能,一个最常见 ...

  5. 使用 Drools 规则引擎实现业务逻辑,可调试drl文件

    http://www.srcsky.com/tech/arts/389.html 代码下载http://download.csdn.net/detail/zhy011525/2462313 使用 Dr ...

  6. 使用 Drools 规则引擎实现业务逻辑

    要求施加在当今软件产品上的大多数复杂性是行为和功能方面的,从而导致组件实现具有复杂的业务逻辑.实现 J2EE 或 J2SE 应用程序中业务逻辑最常见的方法是编写 Java 代码来实现需求文档的规则和逻 ...

  7. 详解:Drools规则引擎探究

    引入 ▐ 问题引入 天猫奢品业务方为了吸引更多的新客,和提高会员的活跃度,做了一期活动,通过购买天猫奢品频道内的任意商品就赠送特殊积分,积分可以直接兑换限量的奢品商品.假如业务方给的规则如下: 主刃同 ...

  8. drools规则引擎因为内存泄露导致的内存溢出

    进入这个问题之前,先了解一下drools: 在很多行业应用中比如银行.保险领域,业务规则往往非常复杂,并且规则处于不断更新变化中,而现有很多系统做法基本上都是将业务规则绑定在程序代码中. 主要存在的问 ...

  9. SpringBoot2 整合 Drools规则引擎,实现高效的业务规则

    本文源码:GitHub·点这里 || GitEE·点这里 一.Drools引擎简介 1.基础简介 Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的 ...

最新文章

  1. 安装VMware ESXi 6 RC版
  2. windows安装配置git和Tortoisegit
  3. 反向非归零编码_(宏)基因组编码基因预测
  4. VTK:可视化之ComplexV
  5. python类class基础
  6. bzoj3122 [Sdoi2013]随机数生成器(bsgs+扩欧+数列)
  7. 检测窥屏_开挂、狙击、窥屏?乱象丛生的炉石狂野天梯,到底怎么了?
  8. [导入]Visual Studio 2005 Team Edition软件架构系列课程(1): 概述
  9. 10分钟学会python函数式编程
  10. FileStream对象的使用
  11. ae万能弹性表达式_干货丨AE表达式知多少?4大常用表示式解决80%难题
  12. 基于java的飞机大战雷电游戏的开发与设计#毕业设计
  13. Webmagic爬虫框架
  14. 2020年整理的大数据基础入门教程总结和学习路线
  15. chrome扩展设置代理
  16. Spring Boot入门系列(六)Spring Boot如何整合Mybatis【附详细步骤】
  17. win10系统的计算机C盘在哪,win10系统只有一个C盘怎么解决
  18. CString怎么转成LPVOID的问题 vc/mfc
  19. 微软.net精简框架最常见问题
  20. Python数据容器、list列表、tuple元组、str字符串、数据容器(序列)切片、set集合、dict字典、字符串大小比较

热门文章

  1. 蓝桥杯 ALGO-93 算法训练 反置数
  2. [Python] L1-026. I Love GPLT-PAT团体程序设计天梯赛GPLT
  3. 1051. 复数乘法 (15)-PAT乙级真题
  4. asset文件夹路径 unity_Unity Assets目录下的特殊文件夹名称
  5. 关于Oracle默认用户名system密码不正确登录不上解决方案
  6. MyBatis中Like语句使用方式
  7. csharp datagridview to a datatable,a dataset
  8. 计算机程序的思维逻辑 (91) - Lambda表达式
  9. 单例模式与线程安全问题浅析
  10. 判断两个IP大小关系及是否在同一个网段中