这是我参与「第五届青训营 」笔记创作活动的第4天。本次上传的是规则引擎相关内容
规则引擎
概述
规则引擎是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。 将业务决策和程序本身做解耦,提高稳定性。 开发人员维护规则引擎,由业务人员修改规则决策,不需要重复的代码开发。 优点
- 解决开发人员重复编码的问题
- 业务决策与服务本身解耦,提高服务的可维护性
- 缩短开发路径,提高效率
组成部分
- 数据输入:支持接受使用预定义的语义编写的规则作为策略集。比如 price > 500 接受业务的数据作为执行过程中的参数,比如价格、标签等
- 规则理解:能够按照预先定义的词法、语法、优先级、运算符等正确理解业务规则所表达的语义。正确的理解数据的输入
- 规则执行:根据执行时输入的参数对策略集中的规则进行正确的解释和执行。同时对规则执行过程中的数据类型进行检查,确保执行结果正确
应用场景
- 风控对抗:识别黑灰产,及时调节和优化对抗策略
- 活动运营策略:解耦服务代码和业务运营,提高运营策略的迭代效率
- 数据分析和清洗:定义不同处理规则,方便产出不同的数据
编译原理基本概念
规则引擎的组成部分,其中的几个环节与编译原理对应
- 理解:词法分析、语法分析
- 执行:抽象语法树
- 输入输出:参数注入、类型检查
词法分析
将源代码字符串转化为词法单元 token 的过程
有限状态机:有限自动机就是一个状态机,它的状态数量是有限的。该状态机在任何一个状态,基于输入的字符,都能做一个确定的状态转换。
根据有限状态机输出 token,并将 token 传入下一阶段
语法分析
在词法分析的基础上识别出表达式的语法结构。
抽象语法树
表达式语法结构的树状表达,对于一个表达式,其抽象语法树一定是唯一的 其每个节点(子树)是一个语法单元,这个单元的构成规则叫做"语法"。每个节点还可以有下级节点。
-
上下文无关语法 Context--Free Grammar 语言句子无需考虑上下文,就可以判断正确性。可以使用巴科斯范式 (BNF) 来表达
-
巴科斯范式 (BNF): 产生式:一个表达式可以由另外已知类型的表达式或者符号推导产生。 BNF 的定义中,下层的表达式可用于上层表达式的定义,这种设计其实也表达了运算优先级的涵义。
- 递归下降算法 递归下降算法就是自顶向下构造语法树不断的对 Token 进行语法展开(下降),即当前层次无法满足不了表达时,根据 BNF 的层次关系,下降一层。在展开过程中可能会遇到递归的情况。 识别完成一个表达式之后,需要进行回溯,在回溯的过程中,使用贪心的策略,匹配第一个能够匹配的表达式定义
- 递归下降算法的演示
- 首先分析 price 词法,根据 BNF 下降,直到 pri 层次得到该词为 id。
- 随后分析 > ,此时需要网上回溯,回溯时使用贪心策略,一旦碰到符合表达式,则停止往上。
- 由于 price 自己已经构成一个
cmp的表达式,所以在匹配 > 后,需要去匹配add表示。对于 500 这个词,从 cmp 一直递归下降,直到判别为 const 类型,即为结束。 - 之后的过程和上面类似,回溯 && 符号,再下降。
- 最后得到的抽象语法树会带有括号,但实际上的抽象语法树不用带括号,因为树已经表现出了优先级大小。
最后结果
类型检查
类型检查:验证执行的结果是否为合适的数据类型。在抽象语法树中,通常会验证某节点的子节点的数据类型是否合法
- 类型综合:根据子表达式的类型构造出父表达式的类型。例如,表达式 A+B 的类型是根据 A 和 B 的类型定义的。
- 检查时机:类型检查可以发生在表达式编译阶段,即在构造抽象语法树的时候,可以发生在执行时的阶段。
- 编译时:如果常量的检查,那么可以直接判断;但是对于变量来说,需要提前声明参数的类型,在构建语法树的时候进行类型检查。
-
- 执行时:可以根据执行时的参数输入的值类型,在执行过程中进行类型检查
- 执行时:可以根据执行时的参数输入的值类型,在执行过程中进行类型检查
- 编译时:如果常量的检查,那么可以直接判断;但是对于变量来说,需要提前声明参数的类型,在构建语法树的时候进行类型检查。
参数注入:在规则执行过程中,使用输入的参数值来计算语法树中的标识符节点值的过程