定义
规则引擎是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。
规则本质上是一个函数,如y=f(x1,x2,..,xn)
规则引擎由三部分
• 事实(Fact):就是用户输入的已经事实,可以理解为推理前的已知对象。
• LHS(Left Hand Side):可以理解为规则执行需要满足的条件。
• RHS(Right Hand Sike):可以理解为规则执行后的返回对象。
方案模型
image.png
两个重要模块:
• 规则管理:可以理解为逻辑上管理规则,主要涉及规则、事实对象和规则集三个实体。涉及到规则变更时,最好对规则加个版本,可通过规则版本控制,可以平滑灰度地方式改变规则,也便于更有信心在测试规则正确性。
• 规则执行:通过规则库数据,通过规则引擎的规则解析、规则编译将可执行代码缓存起来,避免每次和DB交互,然后每次规则的变更也通过ZK或者DCC实时通知给规则执行器。规则执行器的实现方式,可以多种多样,不依赖于规则库的存储方式,根据需求,这里选用Drools 可以基于ANTLR定制Rules 来作为规则引擎的核心。
规则管理:由于多节点部署,规则主要存放在数据库中进行统一管理。
由于Drools的KieFileSystem需要管理目录的为src/main/resources,所以临时生成的DRL文件可能需要再次编译。
由方案可以得出规则引擎需要的模块有
1.规则生成服务
2.日志系统
3.规则重载
4.规则执行
5.消息系统
6.规则多节点同步
主要需要设计的内容是 规则生成服务。
需要定义不同类型的规则及其生成机制,规则执行的时候可以通过不同的规则类型通过不同的执行器来执行规则。
具体实现:
业务规则引擎主要包含如下模块
- BusinessRuleExecutor 规则引擎配置执行器接口:主要用来定义获取业务规则配置的动作方式。
- BusinessRuleExecutorImpl 规则引擎配置加载模块:实现了BusinessRuleExecutor接口。用于动态加载和执行规则。
- BusinessRule 业务规则元素:定义业务规则的接口,主要包含:业务规则标识、业务规则内容。
- BusinessRuleRunner 业务规则引擎执行器:主要是执行具体的业务规则脚本代码,触发相应的事件判断。
类图层次结构如下所示
日志服务在调用接口的时候或者执行规则前后都会打点,根据需要是否持久化存储日志信息。
消息系统功能:
1.在规则执行完后,会根据结果调用外部服务。
2.新生成规则后,根据配置是否需要立即更新规则库,并通知其他节点。
规则体大致可以抽象为4大属性:
名称 描述
trigger 表示场景的触发器,例如时间点、设备属性、设备事件等
condition 表示场景被触发后的过滤条件,例如时间段限制、设备属性限制。一个场景中可以有多个过滤条件,彼此之间是“与”的关系。场景中也可以没有过滤条件,这时场景触发后会不经过滤直接执行相应的动作。
action 表示场景被触发,且满足过滤条件时,所需执行的动作,例如设置设备属性、执行另一个场景。一个场景中可以有多个动作。场景中必须至少有一个动作。
type 表示场景规则的类型
以如下为例,整个规则引擎流程
{
"type":"IFTTT", #为后续扩展,后续扩展不同的规则
"trigger":{
"uri":"trigger/device/event",
"params":{
"productId": "product id",
"deviceId":"iot device code",
"propertyName":"msgType",
"compareType":"equals",
"compareValue":"videoMotion"
}
},
"condition":{
"uri":"logical/and", # 有logical/and
"items":[
{
"uri":"condition/timeRange",
"params":{
"cron":"0 15 10 ? * MON-FRI",
"cronType":"quartz_cron"
}
},
{
"uri":"condition/device/property",
"params":{
"productId":"pkxxxxon",
"deviceId":"txxxxce",
"propertyName":"soxxxxrty",
"compareType":"<",
"compareValue":10
}
}
]
},
"action":[
{
"uri":"action/device/setProperty",
"params":{
"deviceId":"light_iotId",
"propertyName":"onOff",
"propertyValue":"on"
}
}
]
}
首先把不同的trigger 定义成不同的规则放入trigger的规则库,trigger的规则库主要是为了执行action中匹配
condition的 条件,也就是Trigger是为了分发请求到不同的执行器中执行规则。
而condition和action是真正执行规则的when 和then。
规则生成方案
定义规则模板 ruleTemplate
"package com.dahua.rulesengine\n" +
"\n" +
"import\tcom.dahua.rulesengine.model.RuleResult;\n" +
"<rules; separator="\n\n">\n" +
">>\n" +
"\n" +
"ruleValue(condition,action,rule) ::=<<\n" +
"rule "<rule.name>"\n" +
"\tno-loop true\n" +
"\t\twhen\n" +
"\t\t r){\n" +
" TODO Action1<if(action)>,\n" +
" TODO Action2<endif>)\n" +
" }\n" +
"end\n" +
">>\n";
参数转换成 规则JSON //这里可以进一步封装成POJO类 映射的时候能更加规范,设置值得时候也不会出错
Map<String, Object> map = new HashMap<>();
//组合Rule部分
Map<String, Object> rule = new HashMap<>();
rule.put("name", name);
map.put("rule", rule);
//组合 规则When部分
Map<String, Object> when = new HashMap<>();
when.put("property","moneySum");
when.put("compare"," >");
when.put("value"," 500");
map.put("condition", when);
//组合 规则Then部分
Map<String, Object> then = new HashMap<>();
then.put("money", money);
map.put("action", then);
//组合规则When And Then 部分
return JSONObject.toJSONString(map);
通过antlr包定制rule
STGroup group = new STGroupString(ruleTemplate);
ST stFile = group.getInstanceOf("wordImport");
ST stRule = group.getInstanceOf("ruleValue");
JSONObject jsonObject = JSONObject.parseObject(json);
JSONObject condition = jsonObject.getJSONObject("condition");
JSONObject action = jsonObject.getJSONObject("action");
JSONObject rule = jsonObject.getJSONObject("rule");
stRule.add("condition", condition);
stRule.add("action", action);
stRule.add("rule", rule);
stFile.add("rules", stRule);
String result = stFile.render();
return result;
在生成规则后获取 rule.hashcode()查询有没有入库
如果已经入库,则给已经入库的规则添加新的condition和action。
若是调用规则执行服务,
通过封装的Facts POJO类 接收参数
调用trigger规则执行器,如果条件触发规则调用,继续执行该trigger业务规则执行器,对比condition 从而执行action(此时会发rpc消息到业务方)
至此 拿到整个规则执行的结果。
网友评论