bobty综合体育在日常业务开发工作中我们经常会遇到一些根据业务规则做决策的场景。为了让开发人员从大量的规则代码的开发维护中释放出来,把规则的维护和生成交由业务人员,为了达到这种目的通常我们会使用规则引擎来帮助我们实现。
本篇文章主要介绍了规则引擎的概念以及Kie和Drools的关系,重点讲解了Drools中规则文件编写以及匹配算法Rete原理。文章的最后为大家展示了规则引擎在催收系统中是如何使用的,主要解决的问题等。
消费贷作为vivo钱包中的重要业务板块当出现逾期的案件需要处理时,我们会将案件统计收集后导入到催收系统中,在催收系统中定义了一系列的规则来帮助业务方根据客户的逾期程度、风险合规评估、操作成本及收益回报最大原则制定催收策略。例如“分案规则” 会根据规则将不同类型的案件分配到不同的队列,再通过队列分配给各个催收岗位和催收员,最终由催收员去进行催收。下面我会结合具体场景进行详细介绍。
可以看出如果规则很多或者比较复杂的场景需要在代码中写很多这样if else的代码,而且不容易维护一旦新增条件或者规则有变更则需要改动很多代码。
此时我们需要引入规则引擎来帮助我们将规则从代码中分离出去,让开发人员从规则的代码逻辑中解放出来,把规则的维护和设置交由业务人员去管理。
规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件, 实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。
通过接收数据输入解释业务规则,最终根据业务规则做出业务决策。常用的规则引擎有:Drools,easyRules等等。本篇我们主要来介绍Drools。
在介绍Drools之前我们不得不提到一个概念KIE,KIE(Knowledge Is Everything)是一个综合性项目,将一些相关技术整合到一起,同时也是各个技术的核心,这里面就包含了今天要讲到的Drools。
Drools是一个业务规则管理系统,具有基于前向链和后向链推理的规则引擎,允许快速可靠地评估业务规则和复杂的事件处理。
jBPM是一个灵活的业务流程管理套件,允许通过描述实现这些目标所需执行的步骤来为您的业务目标建模。
OptaPlanner是一个约束求解器,可优化员工排班、车辆路线、任务分配和云优化等用例。
Drools 的基本功能是将传入的数据或事实与规则的条件进行匹配,并确定是否以及如何执行规则。
Drools的优势:基于Java编写易于学习和掌握bobty综合体育,可以通过决策表动态生成规则脚本对业务人员十分友好。
当用户在 Drools 中添加或更新规则相关信息时,该信息会以一个或多个事实的形式插入 Drools 引擎的工作内存中。Drools 引擎将这些事实与存储在生产内存中的规则条件进行模式匹配。
当满足规则条件时,Drools 引擎会激活并在议程中注册规则,然后Drools 引擎会按照优先级进行排序并准备执行。
DRL 文件中的查询是在 Drools 引擎的工作内存中搜索与 DRL 文件中的规则相关的事实。在 DRL 文件中添加查询定义,然后在应用程序代码中获取匹配结果。查询搜索一组定义的条件,不需要when或then规范。
通过 KIE 会话配置在 Drools 引擎的工作内存中设置全局值,在 DRL 文件中的规则上方声明全局变量,然后在规则的操作 ( then) 部分中使用它。
当事实被插入到工作内存中后,规则引擎会把事实和规则库里的模式进行匹配,对于匹配成功的规则再由 Agenda 执行推理算法中规则的(then)部分。
规则的“when”部分也称为规则的左侧 (LHS)包含执行操作必须满足的条件。如果该when部分为空,则默认为true。如果规则条件有多个可以使用(and,or),默认连词是and。如银行要求申请人年满21岁,那么规则的when条件是Applicant(age 21)
规则的“then”部分也称为规则的右侧(RHS)包含在满足规则的条件部分时要执行的操作bobty综合体育。如银行要求申请人年满 21 岁(Applicant( age 21 ))。不满足则拒绝setApproved(false)
Drools主要通过insert、update方法对工作内存中的fact数据进行操作,来达到控制规则引擎的目的。
操作完成之后规则引擎会重新匹配规则,原来没有匹配成功的规则在我们修改完数据之后有可能就匹配成功了。
注意:这些方导致重新匹配,有可能会导致死循环问题,在编写中最好设置属性no-loop或者lock-on-active属性来规避。
说明:kmodule是6.0 之后引入的一种新的配置和约定方法来构建 KIE 库,而不是使用之前的程序化构建器方法。
KBase的default属性表示当前KBase是不是默认的,如果是默认的则不用名称就可以查找到该 KBase,但每个 module 最多只能有一个默认 KBase。
KieServices:可以访问所有 Kie 构建和运行时的接口,通过它来获取的各种对象(例如:KieContainer)来完成规则构建、管理和执行等操作。
KieSession:KieSession是一个到规则引擎的对话连接,通过它就可以跟规则引擎通讯,并且发起执行规则的操作。例如:通过ert方法来将事实(Fact)插入到引擎中,也就是Working Memory中,然后通过kSession.fireAllRules方法来通知规则引擎执行规则。
Rete算法由Charles Forgy博士发明,并在1978-79年的博士论文中记录。Rete算法可以分为两部分:规则编译和运行时执行。
编译算法描述了如何处理生产内存中的规则以生成有效的决策网络。在非技术术语中,决策网络用于在数据通过网络传播时对其进行过滤。
【BetaNode】:用于比较两个对象,两个对象可能是相同或不同的类型。上述案例中用到的join node就是betaNode的一种类型。join node 用于连接左右输入,左部输入的是事实对象列表,右部输入一个事实对象,在Join节点按照对象类型或对象字段进行比对。BetaNodes 也有内存。左边的输入称为 Beta Memory,它会记住所有传入的对象列表。右边的输入称为 Alpha Memory,它会记住所有传入的事实对象。
表示一条规则已匹配其所有条件,带有“或”条件的规则会为每个可能的逻辑分支生成子规则,因此一个规则可以有多个终端节点。
取出一个模式例如a1==1(模式:就是指when语句的条件,这里when条件可能是有几个更小的条件组成的大条件。模式就是指的不能再继续分割下去的最小的原子条件),检查参数类型(ObjectTypeNode),如果是新类型则加入一个类型节点;
检查模式的条件约束:对于单类型约束a1==1,检查对应的alphaNode是否已存在,如果不存在将该约束作为一个alphaNode加入链的后继节点;
若为多类型约束a1==b1,则创建相应的betaNode,其左输入为LeftInputAdapterNode,右输入为当前链的alphaNode;
重复3-5,直到所有的模式处理完毕,创建TerminalNode,每个模式链的末尾连到TerminalNode;
从工作内存中取一工作存储区元素WME(Working Memory Element,简称WME)放入根节点进行匹配。WME是为事实建立的元素,是用于和非根结点代表的模式进行匹配的元素。
遍历每个alphaNode和ObjectTypeNode,如果约束条件与该WME一致,则将该WME存在该alphaNode的匹配内存中,并向其后继节点传播。
对每个betaNode进行匹配,将左内存中的对象列表与右内存中的对象按照节点约束进行匹配,符合条件则将该事实对象与左部对象列表合并,并传递到下一节点。
和3都完成之后事实对象列表进入到TerminalNode。对应的规则被触活,将规则注册进议程(Agenda)。
事实集合中的每次变化,其匹配后的状态都被保存到alphaMemory和betaMemory中bobty综合体育。在下一次事实集合发生变化时(绝大多数的结果都不需要变化)通过从内存中取值,避免了大量的重复计算。
Rete算法主要是为那些事实集合变化不大的系统设计的,当每次事实集合的变化非常剧烈时,rete的状态保存算法效果并不理想。
存在状态重复保存的问题,匹配过多个模式的事实要同时保存在这些模式的节点缓存中,将占用较多空间并影响匹配效率。
不适合频繁变化的数据与规则(数据变化引起节点保存的临时事实频繁变化,这将让rete失去增量匹配的优势;数据的变化使得对规则网络的种种优化方法如索引、条件排序等失去效果)。
rete算法使用了alphaMemory和betaMemory存储已计算的中间结果, 以牺牲空间换取时间, 从而加快系统的速度。然而当处理海量数据与规则时,beta内存根据规则的条件与事实的数目而成指数级增长, 所以当规则与事实很多时,会耗尽系统资源。
在Drools早期版本中使用的匹配算法是Rete,从6.x开始引入了phreak算法来解决Rete带来的问题。
文章开头问题引出的例子中可以通过编写drl规则脚本实现,每次规则的变更只需要修改drl文件即可。
虽然通过编写drl可以解决规则维护的问题,但是让业务人员去编写这样一套规则脚本显然是有难度的,那么在催收系统中是怎么做的呢,我们继续往下看。
催收系统自研了一套决策表的解决方案,将drl中的条件和结果语句抽象成结构化数据进行存储并在前端做了可视化页面提供给业务人员进行编辑不需要编写规则脚本。例如新增规则:
表中的每一行都对应一个rule,业务人员可以根据规则情况进行修改和添加,同时也可以根据条件定义对决策表进行拓展。
催收系统提供了可视化页面配置来动态生成脚本的功能(业务人员根据条件定义和结果定义来编辑决策表进而制定相应规则)。
1.根据规则类型解析相应的事实对象映射文件,并封装成条件实体entitys与结果实体resultDefs,文件内容如下图:
本文主要由催收系统中的一个案例引出规则引擎Drools,然后详细介绍了Drools的概念与用法以及模式匹配的原理Rete算法。最后结合催收系统给大家讲解了Drools在催收系统中是如何使用的。
通过规则引擎的引入让开发人员不再需要参与到规则的开发与维护中来,极大节约了开发成本。通过自研的催收系统可视化决策表,让业务人员可以在系统中灵活配置维护规则而不需要每次编写复杂的规则脚本,解决了业务人员的痛点。系统本质上还是执行的规则脚本,我们这里是把脚本的生成做了优化处理,先通过可视化页面录入规则以结构化的数据进行存储,再将其与规则定义进行整合拼装,最终由系统自动生成规则脚本。