规则引擎核心概念:五个你必须吃透的基石
规则引擎这东西,说复杂也复杂,说简单也简单。我刚开始接触的时候,被一堆术语搞得晕头转向。后来带团队做项目,发现很多问题都出在没搞懂这几个核心概念上。
今天咱们就把这五个概念掰开揉碎。你吃透了它们,后面配置规则就跟玩似的。
核心五件套:规则(Rule)、事实(Fact)、工作内存(Working Memory)、推理引擎(Inference Engine)、议程(Agenda)。这五个概念构成了规则引擎的完整运行闭环。
1. 规则 (Rule) —— 你的业务逻辑说明书
规则是什么?说白了就是「如果...那么...」的句子。比如:如果订单金额超过1000元,那么打9折。
在规则引擎里,规则通常由两部分组成:
- 条件部分 (LHS - Left Hand Side):描述什么时候触发这条规则
- 动作部分 (RHS - Right Hand Side):描述触发后要做什么
我见过很多新手把规则写得又长又臭。其实好的规则就像好的代码——短小、专注、只做一件事。
// 一个典型的规则示例(Drools语法)
rule "高价值客户折扣"
when
$order: Order(amount > 1000)
$customer: Customer(level == "VIP")
then
$order.setDiscount(0.15);
System.out.println("VIP客户大额订单,享受15%折扣");
end
我的习惯:每条规则只写一个核心条件。如果条件太多,拆成多条规则,让引擎自己去组合。这样维护起来轻松很多。
2. 事实 (Fact) —— 你手里的数据牌
事实就是你要处理的数据。订单信息、用户资料、库存数量……这些都是事实。
规则引擎不会自己去数据库里捞数据。你得主动把事实「塞」进引擎里。我刚开始做的时候老忘记这步,结果规则怎么都不触发,排查了半天……
// 把事实插入工作内存
KieSession kieSession = kieContainer.newKieSession();
Order order = new Order(1500.0, "VIP");
Customer customer = new Customer("张三", "VIP");
kieSession.insert(order); // 插入事实
kieSession.insert(customer); // 插入事实
kieSession.fireAllRules(); // 触发规则
事实有几个特点你得记住:
- 不可变性:事实一旦插入,引擎认为它不会变。如果变了,你得重新插入或更新
- 类型敏感:引擎根据事实的类型去匹配规则的条件
- 可追溯:引擎会记录事实的变化历史,方便调试
我曾经踩过的坑:在规则执行过程中修改了事实对象的属性,但没有调用 update() 方法。结果引擎用的还是旧数据,规则匹配全乱套了。记住:改完事实一定要通知引擎!
3. 工作内存 (Working Memory) —— 引擎的临时工作台
工作内存就是引擎用来存放事实的地方。你可以把它想象成一个临时数据库,专门给规则引擎用的。
所有你插入的事实,都待在工作内存里。引擎在这里面做模式匹配——拿规则的条件去跟事实比对。
| 特性 | 说明 |
|---|---|
| 存储内容 | 所有已插入的事实对象 |
| 生命周期 | 从插入到会话结束,或显式删除 |
| 访问方式 | 只能通过引擎API操作,不能直接访问 |
| 性能影响 | 事实越多,匹配越慢,注意控制规模 |
你想想看,如果工作内存里有10万个事实,引擎要一条条去匹配,那得多慢?所以实际项目中,我一般会控制单次会话的事实数量,超过一定量就分批处理。
4. 推理引擎 (Inference Engine) —— 真正干活的大脑
推理引擎是规则引擎的核心。它负责做三件事:
- 模式匹配:拿规则的条件去跟工作内存里的事实比对
- 冲突解决:多条规则同时满足条件时,决定谁先执行
- 规则执行:按议程的顺序执行规则的动作
推理引擎有两种工作模式:
- 前向链 (Forward Chaining):从事实出发,推导出结论。比如:已知A和B,推出C。这是最常用的模式。
- 后向链 (Backward Chaining):从目标出发,反推需要哪些事实。比如:要证明C,需要A和B。适合诊断、推理场景。
我的经验:90%的业务场景用前向链就够了。后向链虽然强大,但配置复杂,性能也差一些。除非你做的是专家系统、故障诊断这类应用,否则别轻易碰后向链。
5. 议程 (Agenda) —— 规则的排队叫号系统
当推理引擎发现多条规则都满足条件时,谁先执行?这就轮到议程出场了。
议程本质上是一个优先级队列。它把所有被触发的规则排好序,然后一条条执行。
影响议程排序的因素有:
- 优先级 (Salience):数值越高,越先执行。这是最常用的控制手段
- 激活时间 (Activation Time):规则被触发的时间顺序
- 冲突解决策略:引擎内置的排序规则,比如最近优先、最具体优先等
// 设置规则优先级
rule "紧急规则"
salience 100
when
// 条件
then
// 动作
end
rule "普通规则"
salience 0
when
// 条件
then
// 动作
end
一个小技巧:优先级别设得太极端。我见过有人设10000和-10000,结果后面想插个中间优先级都找不到位置。一般0-100的范围就够用了。
五个概念怎么串起来?
咱们用个实际场景走一遍流程:
- 你创建了一个会话,工作内存是空的
- 你插入一个订单事实(金额2000元)到工作内存
- 推理引擎开始匹配,发现有一条规则「金额>1000打9折」的条件满足了
- 这条规则被放到议程里,排好队
- 你调用
fireAllRules(),议程开始执行规则的动作 - 规则执行时修改了订单的折扣,并更新了工作内存
- 如果修改触发了其他规则,引擎会继续匹配,直到没有新规则被触发
嗯,这就是规则引擎的完整运行周期。你想想看,是不是跟咱们平时写if-else差不多?只不过引擎帮你做了自动匹配和排序,省去了你自己写一堆判断逻辑的麻烦。
一句话总结:规则是「剧本」,事实是「演员」,工作内存是「后台」,推理引擎是「导演」,议程是「出场顺序表」。五者配合,才能演好一场业务逻辑的大戏。