Ohhnews

分类导航

$ cd ..
Baeldung原文

Drools中的前向链与后向链:区别、应用与性能考量

#drools#前向链#后向链#规则引擎#java

[LOADING...]

1. 概述

Drools 是一个功能强大的开源业务规则管理系统 (BRMS),用 Java 编写。 它允许开发人员通过以声明性格式编写规则,将业务逻辑与应用程序代码分离。最值得注意的是,这包括提供一个基于前向链接和后向链接推理的规则引擎、一个 DMN 决策引擎以及其他项目。

在本教程中,我们将主要关注前向链接和后向链接,强调它们之间的差异、用例和性能影响。如果您刚开始使用 Drools,请查阅我们的介绍Spring 集成文章,因为我们的示例代码将基于它们。

2. 前向链接

前向链接从已知事实开始,并积极应用规则来生成新事实。 引擎评估所有可用数据,触发匹配的规则,并继续此过程,直到无法得出更多结论。

在数据驱动的方法中,将事实插入 Drools 的工作内存会立即触发其条件与这些事实匹配的规则。这些规则会创建新事实,新事实又会激活更多规则,从而形成一个级联的推理链。因此,前向链接能够动态响应不断变化的数据,使其非常适合监控系统、实时分析或基于流的处理等环境: [LOADING...]

例如,在电信配置引擎中,添加具有特定计划的客户会立即启动一系列配置——更新账单、编程交换机、调整记录以及跨多个系统进行协调。

让我们看几个为前向链接设计的规则:

dialect  "mvel"
    rule "Suggest Manager Role"
        when
            Applicant(experienceInYears > 10)
            Applicant(currentSalary > 1000000 && currentSalary <= 2500000)
        then
            suggestedRole.setRole("Manager");
    end
    rule "Suggest Senior Developer Role"
        when
            Applicant(experienceInYears > 5 && experienceInYears <= 10)
            Applicant(currentSalary > 500000 && currentSalary <= 1500000)
        then
            suggestedRole.setRole("Senior developer");
    end
    rule "Suggest Developer Role"
        when
            Applicant(experienceInYears > 0 && experienceInYears <= 5)
            Applicant(currentSalary > 200000 && currentSalary <= 1000000)
        then
            suggestedRole.setRole("Developer");
    end

设置好规则后,让我们看看前向链接的实际运行:

$ java
private void forwardChaining() {
    KieSession ksession = new DroolsBeanFactory().getKieSession();
    Applicant applicant = new Applicant("Daniel", 38, 1_600_000.0, 11);
    SuggestedRole suggestedRole = new SuggestedRole();
    ksession.setGlobal("suggestedRole", suggestedRole);
    ksession.insert(applicant);
    int fired = ksession.fireAllRules();
    System.out.println("Rules fired: " + fired);
    System.out.println("Suggested role: " + suggestedRole.getRole());
    ksession.dispose();
}

根据我们设置的规则,控制台应该显示一条规则被触发,并且建议的角色是经理

3. 后向链接

后向链接采取相反的方法。它不是从数据开始,而是从目标或查询开始。 引擎然后向后工作,以确定哪些事实或规则可以支持该结论。

在 Drools 中,后向链接通过查询和逻辑插入来实现。当一个规则或查询请求一个事实时,Drools 会搜索可以逻辑推断该事实的规则。如果找到匹配项,它会尝试满足触发这些规则所需的条件,递归地朝着初始目标工作: [LOADING...]

它在问询系统(例如诊断工具或查询驱动的应用程序)中特别有效。例如,我们可以在保险中使用后向链接来识别哪些保单在特定再保险合同的承保范围内。

让我们看一些规则和查询来演示后向链接:

dialect  "mvel"
    query belongsTo(String x, String y)
      Fact(x, y;)
      or
      (Fact(z, y;) and belongsTo(x, z;))
    end
    rule "Great Wall of China BELONGS TO Planet Earth"
    when
        belongsTo("Great Wall of China", "Planet Earth";)
    then
        result.setValue("Decision one taken: Great Wall of China BELONGS TO Planet Earth");
    end
    rule "print all facts"
    when
        belongsTo(element, place;)
    then
        result.addFact(element + " IS ELEMENT OF " + place);
    end

现在,让我们运行这些规则:

$ java
public Result backwardChaining() {
    Result result = new Result();
    KieSession ksession = new DroolsBeanFactory().getKieSession();
    ksession.setGlobal("result", result);
    ksession.insert(new Fact("Asia", "Planet Earth"));
    ksession.insert(new Fact("China", "Asia"));
    ksession.insert(new Fact("Great Wall of China", "China"));
    ksession.fireAllRules();
    return result;
}

结果,我们应该看到以下流程:

$ plaintext
Decision one taken: Great Wall of China BELONGS TO Planet Earth
Great Wall of China IS ELEMENT OF China
Asia IS ELEMENT OF Planet Earth
China IS ELEMENT OF Asia
Great Wall of China IS ELEMENT OF Planet Earth
Great Wall of China IS ELEMENT OF Asia
China IS ELEMENT OF Planet Earth

4. 混合推理

Drools 支持混合推理,允许我们在同一规则集中混合使用两种链接方法。 我们可以使用前向链接被动地处理传入数据,同时使用后向链接查询特定条件。例如,我们可以使用后向链接来验证一个条件,然后触发一个前向链接规则来插入一个新事实,从而桥接两种模式,以实现更灵活、更高效的解决方案。

让我们看一下一个视觉图,说明前向链接和后向链接的工作原理: [LOADING...]

前向链接从已知事实(事实 A、事实 B)开始,触发规则 1,推断出事实 C,然后事实 C 触发规则 2,最后推断出事实 D。

后向链接从目标(事实 D)开始,寻找可能导致它的规则,检查规则 2(需要事实 C),并递归评估必要的事实和规则。

5. 性能考量

由于前向链接对所有相关事实进行全局响应,如果您的规则库庞大且数据流频繁,它可能会遇到性能瓶颈。Rete 算法有助于优化模式匹配,但在扩展时仍需考虑。

同时,后向链接是目标特定的,通常执行的规则更少,对于目标逻辑查询来说更精简——但它不会在未提示的情况下自动响应新数据。

因此,我们为实时、自动响应环境选择前向链接,而当精确性和最小化规则遍历很重要时,则选择后向链接。

6. 结论

在本文中,我们探讨了前向链接和后向链接是什么,如何以及何时实现它们,以及它们之间的主要区别。