规则引擎设计与实现|青训营笔记
一、主要内容
- 规则引擎的基础介绍、组成、应用
- 编译原理基本概念:语法分析、词法分析、抽象语法树、类型检查
- 设计一个规则引擎
二、重点知识详解
1.规则引擎
1.1 规则引擎的基础介绍
-
定义
- 规则引擎是嵌入在应用程序中的组件;
- 实现将业务决策从应用代码中分离出来,并使用预定义语义模块编写业务决策;
- 接受数据输入,解释业务规则,并根据业务规则作出业务决策;
-
解决问题
- 解决开发人员重复编码问题
- 业务决策与服务本身解藕,提高服务可维护性,缩短开发路径,提高效率
1.2 组成部分
- 数据输入
- 支持接受预定义语义编写的规则作为策略集
- price > 500
- 接受业务的数据作为执行过程中的参数
- 价格、标签
- 支持接受预定义语义编写的规则作为策略集
- 规则理解
- 能够按照预定义词法、语法、优先级、运算符正确理解业务规则所表达的语义
- 规则执行
- 根据执行时输入的参数对策略集中规则进行正确解释和执行
- 对规则执行过程中数据类型进行检查,确保结果正确;
1.3 应用场景
- 风控对抗
- 黑灰产对抗,策略研发、产品需要根据特征进行快速识别和对抗
- 规则引擎作为风控系统核心,使产研人员不断调整优化对抗策略,实现最好的风控识别效果
- 活动策略运营
- 业务活动的运营需要及时根据用户效果反馈进行运营策略优化调整
- 规则引擎将服务代码与业务逻辑解锁,提高运营策略迭代效率
- 方便新玩法的探索和效果验证
- 数据分析、清洗
- 数据分析系统中使用规则引擎可以便捷地实现对数据进行整理、清洗、转换
- 数据分析师可以根据不同需求自定义数据处理规则 方便快捷的产出所需数据
2. 编译原理基本概念
2.1 词法分析 Lexical Analysis
- 定义:将源代码字符串转换为词法单元(Token)的过程
- 将语句根据词法进行切分,转变成词法逻辑
- 识别token的方法:有限自动机
- 状态机:状态数量有限的
- 该状态机在任何一个状态基于输入的字符可以做确定的状态转换
2.2 语法分析
- 定义:在词法分析基础上识别出表达式的语法结构
2.3 抽象语法树
- 定义:表达式抽象语法结构的树状表示,对于一个表达式,抽象语法树一定是唯一确定的
- 表达式的语法结构使用树进行表达
- 每个节点(子树)是一个语法单元,单元的构成规则是语法
- 每个节点还能有下级节点
- 上下文无关语法 context free grammer
- 语言句子无需考虑上下文就能判断正确性,可以使用巴克斯范式来进行表达(BNF)
- 产生式:一个表达式可以由另外已知类型的表达式或符号推导产生
- 内置符号:字面量(string、bool、number)标识符、运算符
- 基础表达式:常量或标识符
- 乘法表达式:基础表达式|基础表达式*乘法表达式
- 递归下降算法
- 自顶向下构造语法树
- 不断对token进行语法展开,展开过程中可能会遇到递归
2.4 类型检查
- 定义
- 参数注入:在规则执行过程中使用输入的参数值来计算语法树中标识符节点值的过程
- 类型检查:验证执行的结果是否为合适的数据类型;在抽象语法树中通常验证某节点子节点数据类型是否合法;
- 类型综合
- 根据子表达式类型构造出父表达式的类型
- 例:A+B的类型是根据A,B定义的
- 根据子表达式类型构造出父表达式的类型
- 编译时检查&运行时检查
- 类型检查可以发生在表达式编译阶段:构造语法树阶段
- 需要提前声明参数类型
- 在构建语法树过程中进行类型检查
- 也可以发生在执行的阶段
- 可以根据执行时参数输入值类型在执行时检查
- 类型检查可以发生在表达式编译阶段:构造语法树阶段
三、实践练习例——设计一个规则引擎
3.1 设计目标
- 目标
- 支持特定词法、运算符、数据类型、优先级
- 支持基于以上预定义语法的规则表达式的编译和执行
- 词法(合法Token)
- 参数:字母数字下划线
- boolean
- string
- int
- float
- 预定义运算符
- 运算符
- 一元运算符:+ -
- 二元运算符: + - * / % > < >= <= == !=
- 逻辑操作符:&& || !
- 括号:()
- 数据类型
- String
- boolean
- int
- float
- 运算优先级
3.2 设计过程
- 设计词法分析状态机
- 语法分析
- 优先级表达
- 语法树结构
- 一元运算符:左子树为空,右子树为右操作数
- 二元运算符:左子树为左操作数,右子树为右操作数
- ():左子树空,右子树为内部表达式的语法树
3.3 语法树执行和类型检查
- 语法树执行
- 预先定义好每种操作符的执行逻辑
- 对抽象语法树进行后续遍历执行
- 先执行左子树,得到左节点值
- 再执行右子树,得到右节点值
- 最后根据根节点操作符执行得到根节点值
- 类型检查
- 执行时检查
- 在一个节点左右子节点执行完成后校验两个子节点类型是否符合对应操作符的类型检查预设规则
- Comparison 要求左右值都存在且为int float
- Not 要求左节点空,右节点为boolean
四、本节课总结
本节课学习了规则引擎的设计与实现。由于之前在课程中学习了编译原理相关课程,该章节为对其的复习。完成一个整体的规则引擎需要使用大量的traversal和递归算法,因此在具体实践中需要对此进行额外的学习; 规则引擎最困难的内容在于“规则”的指定,即在类型检查中,如何才能检查有问题的语法输入。