规则引擎核心概念:五个你必须吃透的基石

规则引擎这东西,说复杂也复杂,说简单也简单。我刚开始接触的时候,被一堆术语搞得晕头转向。后来带团队做项目,发现很多问题都出在没搞懂这几个核心概念上。

今天咱们就把这五个概念掰开揉碎。你吃透了它们,后面配置规则就跟玩似的。

核心五件套:规则(Rule)、事实(Fact)、工作内存(Working Memory)、推理引擎(Inference Engine)、议程(Agenda)。这五个概念构成了规则引擎的完整运行闭环。

规则引擎核心概念关系图 规则引擎核心概念关系图 推理引擎 规则 (Rule) 事实 (Fact) 议程 (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) —— 真正干活的大脑

推理引擎是规则引擎的核心。它负责做三件事:

  1. 模式匹配:拿规则的条件去跟工作内存里的事实比对
  2. 冲突解决:多条规则同时满足条件时,决定谁先执行
  3. 规则执行:按议程的顺序执行规则的动作

推理引擎有两种工作模式:

  • 前向链 (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的范围就够用了。

五个概念怎么串起来?

咱们用个实际场景走一遍流程:

  1. 你创建了一个会话,工作内存是空的
  2. 你插入一个订单事实(金额2000元)到工作内存
  3. 推理引擎开始匹配,发现有一条规则「金额>1000打9折」的条件满足了
  4. 这条规则被放到议程里,排好队
  5. 你调用 fireAllRules(),议程开始执行规则的动作
  6. 规则执行时修改了订单的折扣,并更新了工作内存
  7. 如果修改触发了其他规则,引擎会继续匹配,直到没有新规则被触发

嗯,这就是规则引擎的完整运行周期。你想想看,是不是跟咱们平时写if-else差不多?只不过引擎帮你做了自动匹配和排序,省去了你自己写一堆判断逻辑的麻烦。

一句话总结:规则是「剧本」,事实是「演员」,工作内存是「后台」,推理引擎是「导演」,议程是「出场顺序表」。五者配合,才能演好一场业务逻辑的大戏。