1 产生背景

企业级管理者可能会在系统生产过程中调整生产策略、物料采购策略等,因此对企业IT系统的开发有着如下的要求:

  1. 为提高效率,管理流程必须自动化,即使现代商业规则异常复杂。
  2. 市场要求业务规则经常变化,IT系统必须依据业务规则的变化快速、低成本的更新。
  3. 为了快速、低成本的更新,业务人员应能直接管理IT系统中的规则,不需要程序开发人员参与。

而项目开发人员则碰到了以下问题:

  1. 程序=算法+数据结构,有些复杂的商业规则很难推导出算法和抽象出数据模型
  2. 软件工程要求从需求->设计->编码,然而业务规则常常在需求阶段可能还没有明确,在设计和编码后还在变化,业务规则往往嵌在系统各处代码中
  3. 对程序员来说,系统已经维护、更新困难,更不可能让业务人员来管理。

因此迫切需要分离商业决策者的商业决策逻辑和应用开发者的技术决策。把这些商业决策放在中心数据库或其他统一的地方,让它们能在运行时(即商务时间)可以动态地管理和修改从而提供软件系统的柔性和适应性。

规则引擎正是应用于上述动态环境中的一种解决方法。

2 定义

规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据规则做出业务决策。

3 原理

规则引擎可以在系统工作时,将外部的业务规则加载到系统中,并使得系统按照该业务规则进行工作。接下来我们分别进行介绍。

3.1 业务规则

一个业务规则包含一组条件和在此条件下执行的操作,它们表示业务规则应用程序的一段业务逻辑。业务规则通常应该由业务分析人员和策略管理者开发和修改,但有些复杂的业务规则也可以由技术人员使用面向对象的技术语言或脚本来定制。业务规则的理论基础是:设置一个或多个条件,当满足这些条件时会触发一个或多个操作。

3.2 规则引擎的功能

由于规则引擎是软件组件,所以只有开发人员才能够通过程序接口的方式来使用和控制它,规则引擎的程序接口至少包含以下几种API:

  • 加载和卸载规则集的API;
  • 数据操作的API;
  • 引擎执行的API。

开发人员在程序中使用规则引擎基本遵循以下5个典型的步骤:

  1. 创建规则引擎对象;
  2. 向引擎中加载规则集或更换规则集;
  3. 向引擎提交需要被规则集处理的数据对象集合;
  4. 命令引擎执行;
  5. 导出引擎执行结果,从引擎中撤出处理过的数据。

使用了规则引擎之后,许多涉及业务逻辑的程序代码基本被这五个典型步骤所取代。一个开放的业务规则引擎应该可以”嵌入”在应用程序的任何位置,不同位置的规则引擎可以使用不同的规则集,用于处理不同的数据对象。

此外,对使用引擎的数量没有限制。

3.3 规则引擎的架构

规则引擎的架构如下图所示:

规则引擎的原理与功能插图
规则引擎架构

规则引擎的推理步骤如下:

  1. 将初始数据(fact)输入至工作内存(Working Memory)。
  2. 使用Pattern Matcher将规则库(Rules repository)的规则(rule)和数据(fact)比较。
  3. 如果执行规则存在冲突(conflict),即同时激活了多个规则,将冲突的规则放入冲突集合。
  4. 解决冲突,将激活的规则按顺序放入Agenda。
  5. 执行Agenda中的规则。
  6. 重复步骤2至5,直到执行完毕Agenda中的所有规则。

任何一个规则引擎都需要很好地解决规则的推理机制和规则条件匹配的效率问题。

当引擎执行时,会根据规则执行队列中的优先顺序逐条执行规则执行实例,由于规则的执行部分可能会改变工作区的数据对象,从而会使队列中的某些规则执行实例因为条件改变而失效,必须从队列中撤销,也可能会激活原来不满足条件的规则,生成新的规则执行实例进入队列。

于是就产生了一种”动态”的规则执行链,形成规则的推理机制。这种规则的”链式”反应完全是由工作区中的数据驱动的。

规则条件匹配的效率决定了引擎的性能,引擎需要迅速测试工作区中的数据对象,从加载的规则集中发现符合条件的规则,生成规则执行实例。

1982年美国卡耐基·梅隆大学的Charles L. Forgy发明了一种叫Rete算法,很好地解决了这方面的问题。目前世界顶尖的商用业务规则引擎产品基本上都使用Rete算法。

对于Rete算法,网络上有很多资料,理解起来不是太复杂。本文以介绍框架为主,因此不再详述。其中接下来要介绍的Drools也使用了Rate算法。

4 规则引擎框架

Java规则引擎主要有JRules/Drools/JLisa/QuickRules等。我们以开源项目Drools进行介绍。

Drools是用Java语言编写的开放源码规则引擎,使用Rete算法对所编写的规则求值。Drools允许使用声明方式表达业务逻辑。可以使用非XML的本地语言编写规则,从而便于学习和理解。

并且,还可以将Java代码直接嵌入到规则文件中,这令Drools的学习更加吸引人。Drools有如下特点;

  • 完整的实现了Rete算法;
  • 提供了强大的Eclipse Plugin开发支持;
  • 通过使用其中的DSL(Domain Specific Language),可以实现用自然语言方式来描述业务规则,使得业务分析人员也可以看懂业务规则代码;
  • 提供了基于WEB的BRMS——Guvnor,Guvnor提供了规则管理的知识库,通过它可以实现规则的版本控制,及规则的在线修改与编译,使得开发人员和系统管理人员可以在线管理业务规则。

规则引擎的原理简图如下:

规则引擎的原理与功能插图1
规则引擎原理简图

Drools规则文件有一个或多个rule声明。每个rule声明由一个或多个conditional元素以及要执行的一个或多个consequences或actions组成。

一个规则文件还可以有多个(即0个或多个)import声明、多个global声明以及多个 function 声明。下面我们看一个规则文件的示例:

rule "Tests for type1 machine"
salience 100
when
   machine : Machine( type == "Type1" )
then
   Test test1 = testDAO.findByKey(Test.TEST1);
   Test test2 = testDAO.findByKey(Test.TEST2);
   Test test5 = testDAO.findByKey(Test.TEST5);
   machine.getTests().add(test1);
   machine.getTests().add(test2);
   machine.getTests().add(test5);
   insert( test1 );
   insert( test2 );
   insert( test5 );
end

其中:

  • rule 声明有一个惟一标识它的 name
  • salience属性可以让规则执行引擎知道应该启动规则的结果语句的顺序。
  • when 关键词定义规则中的条件块
  • then 关键词定义结果块。当其上部的条件满足时,该结果块的规则被执行。

因此,整个规则的定义非常简单,便于使用。

原文链接:https://zhuanlan.zhihu.com/p/51296996



规则引擎的原理与功能插图2

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:https://choupangxia.com/2020/11/28/rule-engine-2/