后端与规则引擎设计与实现|青训营笔记

96 阅读4分钟

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

一、本章重要知识点

1、理解规则引擎的组成部分及应用场景

2、理解规则引擎的核心原理—编译原理的相关概念

3、设计并实现一个规则引擎—YoungEngine

4、结合知识,实现一个Web版规则引擎

二、详细知识介绍

1.认识规则引擎

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

  • 解决开发人员重复编码的问题
  • 业务决策和服务本身解耦,提高服务的可维护性
  • 缩短开发路径,提高效率

组成部分

  • 数据输入
  • 规则理解
  • 规则执行

应用场景

  • 风控对抗
  • 活动策略运营
  • 数据分析和清洗

2.编译原理基本概念

介绍编译、词法分析、语法分析、抽象语法树等概念

词法分析

把源码字符串转换为词法单元(Token)的这个过程

语法分析

在词法分析的基础上识别出表达式的语法结构的过程

抽象语法树

表达式抽象语法结构的树状表示,对于一个表达式,抽象语法树一定是唯一确定的

类型检测

验证执行的结果是否为合适的数据类型。 在抽象语法树中,通常会验证某节点的子节点的数据类型是否合法

  • 类型综合

    根据子表达式的类型构造出父表达式的类型。

  • 编译时检查&运行时检查

    类型检查可以发生在表达式的编译阶段,即在构造语法树的阶段,也可以发生在执行时的阶段

3.设计一个规则引擎

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

4.规则引擎的实现

使用Hertz框架开发一个HTTP服务,服务使用mysql,支持表达式的增删查改和编译执行。

并实现以下接口

直接表达式执行

请求参数为待执行的表达式和表达式中参数的值,并输出编译结果

  • POST api/engine/run
  • Request
{
    "exp": "uid == 12345 && did > 0",
    "params": {
        "uid": 123456,
        "did": 0
    }
}
  • Response
{
    "code": 0,
    "message": "success",
    "data": {  // 执行结果
        "result": true
    }
}

新增表达式

新增一条表达式到DB中,并返回表达式在DB中的ID

需要检测表达式是否已经存在,如果已经存在,直接返回表达式的ID

需要检测表达式是否合法(编译是否通过) ,如果编译失败,返回错误码 20001和编译错误

  • POST api/engine/exp/new
  • Request
{
    "exp": "uid == 12345 && did > 0",
}
  • Response
{
    "code": 0,
    "message": "success",
    "data": {  // 表达式ID
        "id": 1
    }
}
// 编译失败时
{
    "code": -1,
    "message": "compile error: xxxxx", // 编译失败的信息
    "data": {  // 表达式ID
        "id": 0
    }
}

查询表达式

查询数据库中所有的表达式

  • GET api/engine/exp/list
  • Response
{
    "code": 0,
    "message": "success",
    "data": [  
        {
            "id": 1,
            "exp": "uid > 0"
        }
    ]
}

删除表达式

根据ID删除表达式,表达式不存在时返回错误码20002 , 和错误信息

删除成功返回被删除的表达式信息

  • DELETE api/engine/exp/:id
  • Response
// 删除成功时
{
    "code": 0,
    "message": "success",
    "data": {  // 表达式ID
        "id": 1,
        "exp": "uid > 0"
    }
}// 删除失败时
{
    "code": -1,
    "message": "exp id 1 not exist", //查询失败的信息
    "data": {}
}

执行表达式

根据表达式的ID,查询出表达式内容,并编译执行。表达式不存在时返回错误码20002 , 和错误信息

  • POST api/engine/exp/run
  • Request
{
    "exp_id": 1,
    "parmas": {
        "uid": 123456,
        "did": 0
    }
}
  • Response
{
    "code": 0,
    "message": "success",
    "data": {  // 执行结果
        "result": true
    }
}// 表达式不存在时
{
    "code": -1,
    "message": "exp id 1 not exist", //查询失败的信息
    "data": {}
}