规则引擎 | 青训营笔记

128 阅读7分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 15 天

认识规则引擎

例如:抖音商城搞活动,你买东西,我就送你积分。根据买的东西不同,送不同的积分:

image-20230129140706338

运营&PR:哎呀,规则要改,要加好多不同的价格档位。。。再来!

image-20230129140809872

运营&PR:再来!新用户多给一点,促销。老用户少给点嘛。。。RD:阿里嘎多运营&PR桑......

  • 抽象一个专门的组件出来,解决这些逻辑耦合:

image-20230129141014588

概念

  • 规则引擎是一种嵌入在应用服务中的组件,可以将灵活多变的业务决策从服务代码中分离出来。通过使用预定义的语义模块来编写业务逻辑规则。在执行时接受数据输入、解释业务规则,并做出决策。规则引擎能大大提高系统的灵活性和扩展性。

业务决策&代码解耦

引入规则引擎后的前后对比:

image-20230129141314081

解决开发人员重复编码的问题。

业务决策与服务本身解耦,提高服务的可维护性

缩短开发路径,提高效率。

规则引擎组成部分

  • 数据输入:支持接受使用预定义的语义编写的规则作为策略集。比如“price> 500”。接受业务的数据作为执行过程中的参数,比如价格、标签等
  • 规则理解:能够按照预先定义的词法、语法、优先级、运算符等正确理解业务规则所表达的语义。
  • 规则执行:根据执行时输入的参数对策略集中的规则进行正确的解释和执行。同时对规则执行过程中的数据类型进行检查,确保执行结果正确。

应用场景

  • 在字节跳动,规则引擎已经在风控识别、活动运营、数据分析和清洗、配置下发等场景得到了广泛的应用。开发人员可以将业务逻辑与服务代码解耦,实现灵活、高效的业务策略发布。目前公司内部基于规则引擎的动态决策系统已经承接了千万级别QPS的决策请求。
  • 规则引擎的实现需要在满足大容量、高请求、低延迟的基础上尽可能做到简单易上手。本次课程将会带领大家实现一个简单版的规则引擎。

编译原理基本概念

image-20230129142246141

  • 理解:

    • 词法分析: 把源代码字符串转换为词法单元(Token)的这个过程。
    • 语法分析: 在词法分析的基础上识别出表达式的语法结构。
  • 执行:

    • 抽象语法树:表达式抽象语法结构的树状表示,对于一个表达式,抽象语法树一定时唯一确定的。
  • 输入、输出:

    • 类型检查: 验证执行的结果是否为合适的数据类型。在抽象语法树中,通常会验证某节点的子节点的数据类型是否合法。
    • 参数注入: 在规则执行过程中,使用输入的参数值来计算语法树中的标识符节点值的过程。

词法分析

  • 词法分析就是把源代码字符串转换为词法单元(Token)的这个过程。

image-20230129142909710

  • 如何识别Token? 有限状态机(Finite-State Automation)!

    • 有限自动机就是一个状态机,状态数量有限。状态机在任何一个状态,基于输入的字符,都能做一个确定的状态转换。
    • 词法分析的结果,就是产生了一系列的Token。

状态机,就是规则的一个描述昂!只要状态机合理,词法设计就完成啦!!!

语法分析

词法分析基础上,识别表达式的语法结构

image-20230129143111965

抽象语法树

表达式的语法结构可以用树来表示,其每个节点(子树)是一个语法单元,这个单元的构成规则就叫“语法”。每个节点还可以有下级节点。

image-20230129143258545

抽象语法树(AST)

上下文无关语法

  • 上下文无关语法 Context-Free Grammer

语言句子无需考虑上下文,就可以判断正确性,可以使用BNF来表示。

例如:r := a > b,和上下文无关,这里就有个结果昂

  • BNF&表达式:

image-20230129143846030

麻了,毕设里面有AST,我就说怎么这么眼熟啊orz

image-20230129143920480

BNF什么意思:可以递归的表达自己昂!!!

BNF一层一层往上定义的,优先级的定义,就可以放进里面去昂!

递归下降算法

  • 递归下降算法 Recursive Gradient Decent

递归下降算法就是自项向下构造语法树,不断的对Token进行语法展开(下降),展开过程中可能会遇到递归的情况。

  • 从左往右,一步一步进行分析,从上往下一层一层递归,从下往上一层一层回溯,最终构造完成构造出整个树:

image-20230129144922814

image-20230129145219371

类型检查

类型综合

根据子表达式的类型构造出父表达式的类型。例如,表达式A+B的类型是根据A和B的类型定义的。

image-20230129145703463

编译时检查&运行时检查

image-20230129145827577

可以构造的时候做了,也可在执行的过程中再做昂!!!

设计一个规则引擎

设计目标

  • 设计一个规则引擎,支持特定的词法、运算符、数据类型和优先级。并且支持基于以上预定义语法的规则表达式的编译和执行。

image-20230129150205198

词法分析

image-20230129150333319

语法分析

image-20230129150833177

语法树执行与类型检查

image-20230129151143532

规则引擎的实现

课程之前,大家需要根据项目工程,来完成环境的搭建和Demo的运行

项目地址:

github.com/qimengxingy…

相信大家已经完成了Go环境的搭建,项目工程依赖了hertz框架,如果在之前的课程中完成了项目环境搭建可以直接复用。

项目环境:

  • go语言环境搭建

www.runoob.com/go/go-envir…

  • 需要安装docker环境

www.runoob.com/docker/wind…

  • 安装docker-compose工具

www.runoob.com/docker/dock…

项目clone到本地后,可以执行测试脚本来测试环境的可用性。如果有错误欢迎百度和Google解决

1
git clone https://github.com/qimengxingyuan/young_engine.git
2
chmod a+x ./setup.sh
3
./setup.sh
4
复制代码

脚本执行成功,则环境可以支持项目的执行

项目说明:

本项目是一个简单的规则引擎的实现,详细目录可以参考README.md

项目实现时间有限,没有做比较完备的测试,如果在demo执行的过程中出现某些bug或者执行异常可以直接在github提交issue或者修复后提起PR

juejin.cn/post/711798…

自己读读代码昂!

References

  1. 学习资料:juejin.cn/post/719336…
  2. 规则引擎自己,学校里用的少,但是工业界还是用的多的昂!!!
  3. GitHub上的govaluate项目!!!