方罗交接
亚马逊交接
广州同步店铺框架搭建
QPS-Starter 集成文档
刊登规则引擎技术方案
MQ异常补偿方案
负责项目总目录
广州侧同步商品平台
本文档使用 MrDoc 发布
-
+
首页
刊登规则引擎技术方案
## 一. 简介 项目背景是为了解决刊登项目组成员平日解决大量重复BUG。然后通过各个平台返回的常规性报错来设置对应的处理方案。后面在设计研发时又考虑到其它业务平台可能也会有类似方面需求。最后设计成统一公用工具 **源码地址:** http://git.mabangerp.com:2280/mc/product/mc-product-base-modules.git **PS:子项目product-base-modules-drools才是具体的实现方案** ## 二. 设计思路 考虑所有刊登服务或其它业务中心服务都可以快速使用Drools框架, 做出了以下改变: 1. 舍弃了外部配置kmodule.xml 和规则配置文件,**统一外部存储(规则脚本)或内部生成(kmodule.xml)** 2. 集成了以后能根据**不同业务做不同的规则**适配场景 3. 定时获取根据配置的业务编码规则脚本块,内部**自刷新**,无需业务人员做出其它改变 ## 三. POM.XML配置 ```xml <dependency> <groupId>com.mabang.product</groupId> <artifactId>product-base-modules-drools</artifactId> <version>1.0-SNAPSHOT</version> </dependency> ``` ## 四. YAML配置 ```yaml mps: #QPS组件配置 drools: enable: true ruleUrl: http://172.16.20.24:8080/rule/get #${获取规则脚本总控URL,例子上是刊登监控中心总控URL,这个是可以变化的,可以变化的,可以变化的!!! 重要的事情说三遍!! 具体可以参考下方Q&A} refreshInterval: 300 #默认脚本刷新时间300秒 platFormId: 2 #各自平台id, 2:亚马逊 ruleCodes: #业务规则编码集合,至少一个 - code1 "error" - code2 "info" ``` ## 五. drools脚本 · Drools说明: https://blog.csdn.net/chy_18883701161/article/details/124026728 · **注意事项:** 1) 参考该脚本的时候要把这些注释清除掉, 下方脚本都是通过配置mps.drools.ruleUrl接口获取。 2) 不需要配置在自身项目内!!!!!! 3) **技术方案内部都是map入参!!!!!! 因此如果需要新建规则, 只需要修改动态业务条件和处理就行, 一律用Map贯串!!!! 一律用Map贯串!!!! 一律用Map贯串!!!!** · **error.drl** ```drools package rules # 包名 不要改 import java.util.Map; # 引入类名, 不要改 agenda-group "error" # 业务规则编码,用来过滤其它业务规则编码, 可选配置 rule "1" #自定义规则名,不要重复 # 整个条件就是Map里面键值对象error的值是否包含lazada字符串, 包含就去做then的事情。往result键值对对象丢了123字符串, 最后在java使用demo层面去把这个result拿出来 when # 一律用Map贯串!!!! 只能对map里面的键值对做操作 $map : Map(this["error"] matches ".*lazada.*"); then # 往map里面设置结果键值对 $map.put("result", "123"); end rule "2" when $map : Map(this["error"] matches ".*amazon.*"); then $map.put("result1", "456"); end ``` · **info.drl** ```drools package rules # 包名 不要改 import java.util.Map; # 引入类名, 不要改 agenda-group "info" # 业务规则编码,用来过滤其它业务规则编码, 可选配置 rule "1" #自定义规则名,不要重复 # 整个条件就是Map里面键值对象info的值是否包含lazada字符串, 包含就去做then的事情。往resultA键值对对象丢了123字符串, 最后在java使用demo层面去把这个resultA拿出来 when # 一律用Map贯串!!!! 只能对map里面的键值对做操作 $map : Map(this["info"] matches ".*lazada.*"); then # 往map里面设置结果键值对 $map.put("resultA", "123"); end rule "2" when $map : Map(this["info"] matches ".*amazon.*"); then $map.put("result1A", "456"); end ``` ## 六. 使用Demo ```java package com.neo.drools.controller; import com.mabang.product.schema.entity.DroolParamEntity; import com.mabang.product.schema.service.IDroolService; import com.neo.drools.model.Address; import com.neo.drools.model.fact.AddressCheckResult; //import com.neo.drools.service.DroolsBusiness; //import com.neo.drools.service.ReloadDroolsRules; import com.neo.drools.unit.KieUtils; import org.kie.api.runtime.KieSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController public class TestController { @Autowired private IDroolService droolService; // 刷新方法. 本方案支持强制刷新和定时刷新 @RequestMapping("/reload") public String reload() throws Exception { droolService.reload("error"); return "ok"; } // 测试脚本 脚本代码在上方 @RequestMapping("/test") public String test1() throws Exception { DroolParamEntity errorParam = new DroolParamEntity().setParam("error", "lazada and amazon is bad platform"); // before {error=lazada and amazon is bad platform} System.err.println(errorParam.getTransformMap()); DroolParamEntity drool = droolService.drool("error",errorParam); // after {result=123, error=lazada and amazon is bad platform, result1=456} System.err.println(drool.getTransformMap()); // before {error=lazada and amazon is bad platform} DroolParamEntity infoParam = new DroolParamEntity().setParam("info", "lazada and amazon is bad platform"); infoParam = droolService.drool("info", infoParam); // after {result1A=456, info=lazada and amazon is bad platform, resultA=123} System.err.println(infoParam.getTransformMap()); return "ok"; } } ``` **DroolParamEntity.java** ```java package com.mabang.product.schema.entity; import lombok.Data; import java.util.HashMap; import java.util.Map; /** * 类<code>DroolParamEntity</code>说明:参数体 * * @author fangluo * @email fangluo@mabangerp.com * @since 2022/11/3 */ @Data public class DroolParamEntity { /** * 传输map, 参数和结果都在这个map里面拿。 * 为什么不用两个成员属性区分开 ? * 1. 最开始的情景是直接把这个类对象传进去, 但是因为这个类对象在jar包所以就需要破坏双亲委派 * 2. 规则脚本2个map实现起来太繁琐。因此选用一个map包含所有入参及结果 */ private Map<String, Object> transformMap = new HashMap<>(); /** * 设置参数 * * @param key key * @param obj obj * @return 返回当前对象 */ public DroolParamEntity setParam(String key, Object obj) { transformMap.put(key, obj); return this; } } ``` ## 七.Q&A #### 1.为什么需要设置业务编码? 最开始的背景只是为了把各平台返回的错误描述经过规则引擎来得到解决方案。但是为了兼容业务还有其它场景使用规则引擎,因此才加入了业务编码这个业务字段来区分不同平台的不同业务做自己的规则脚本配置 #### 2.为什么需要配置统一ruleUrl?可以不用配置文件里面的接口吗? 为什么需要配置统一ruleUrl,这个作者在研发时是有考量的。因为如果根据每项业务编码去做单独各自配置会浪费很多时间在yml上。还不如做成统一ruleUrl配置。这样节省大家时间。当然这也就造成了获取Drool脚本的URL必须统一。 可以不用配置文件里面**监控中心系统**的接口吗? 这肯定是可以的。只要业务人员自己能提供统一获取符合drools脚本规则的接口,那么是可以替换为自己业务接口。 **源码底层通过接口获取脚本是GET请求,URL拼接设计是:** ```java String url = ${ruleUrl} + "?platformId=" + platFormId + "&ruleCode=" + ruleCode; ``` **响应体:** ```json { // 200是正确码 "code": 200, "data": { // 规则编码 "ruleCode": "error", // 规则脚本 "ruleScript": "package rules \r\n\r\nimport com.mabang.product.schema.entity.DroolParamEntity; \r\n\r\nagenda-group \"error\" \r\nrule \"1\"\r\n when\r\n m : DroolParamEntity( scriptParam.get(\"error\") matches \".*lazada.*\")\r\n then\r\n m.getScriptParam().put(\"result\", \"123\");\r\nend\r\n\r\nrule \"2\"\r\n when\r\n m : DroolParamEntity( scriptParam.get(\"error\") matches \".*amazon.*\")\r\n then\r\n m.getScriptParam().put(\"result1\", \"455\");\r\nend" } } ```
thread
2023年8月24日 10:18
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码