这是我参与「第五届青训营」笔记创作活动的第5天。
本节课程主要介绍了规则引擎以及编译原理相关的知识。
1.规则引擎
规则引擎将业务决策和服务代码分离开来,如运营同学配置活动或者优惠时,可以通过规则引擎自行配置,不用每次涉及到修改业务代码,实现解耦。另外,活动等配置会随着时间越发复杂,规则越来越多,使用规则引擎可以减少开发的压力,减少代码改动以减少bug。规则引擎灵活高效,已经在业界广泛使用。
应用场景主要有风控对抗、活动策略运营、数据分析和清洗。
规则引擎的工作原理与编译原理相关知识联系紧密。规则引擎工作时,需要预先定义一套规则,输入规则引擎;规则引擎进行语法语义分析,理解表达式;之后运行时输入参数,按照预定义的表达式计算返回结果。
2.编译原理
- 词法分析:把源代码字符串转化为词法单元
- 语法分析:在词法分析的基础上,识别表达式的语法结构,构造抽象语法树
- 抽象语法树:表达式的语法结构用树表示,每个节点是语法单元
3.课后作业
使用Hertz框架开发一个HTTP服务,支持新增规则、查询规则、删除规则、执行表达式
路由:
通过GET、POST等方法注册路由到实际执行的函数
g.POST("/engine/exp/new", handler.HandleAddExpression)
新增表达式:
先根据文档定义RuleAddRequest结构体,读取参数。之后使用Compiler方法编译,若不通过则报错返回;若通过,尝试插入数据库。
func HandleAddExpression(ctx context.Context, c *app.RequestContext) {
var req RuleAddRequest
c.Bind(&req)
//编译检查
_, err := Compiler(req.Exp)
if err != nil {
BindResp(c, CompileErrCode, err.Error(), map[string]interface{}{"id": 0})
return
}
//插入DB
exp, err := dal.AddExpression(req.Exp)
if err != nil {
BindResp(c, 20002, "AddExpression failed", exp)
return
}
BindResp(c, SuccessCode, SuccessMsg, exp)
}
运行结果
删除:
实现删除接口时,使用了DELETE方法,取值id的时尝试了几种方法,最后发现使用Param方法可以取到
g.DELETE("/engine/exp/:id", handler.HandleDeleteExpression)
func HandleDeleteExpression(ctx context.Context, c *app.RequestContext) {
id := c.Param("id")
...
}
运行结果
执行表达式:
先根据ID查出规则,之后读取参数,执行
读取规则
exp, e := dal.GetExpressionByID(uint(req.ExpId))
编译,得到语法树
evaluatedExp, err := Compiler(exp.Exp)
代入参数,计算
err = evaluatedExp.Eval(params)
取值
resp, _ := evaluatedExp.GetVal()
运行结果
其余接口略