这是我参与「第五届青训营」伴学笔记创作活动的第14天
前言
对于规则引擎的初次接触了解,以B站开源的gengine规则引擎为对象。
简介
Gengine是一款基于golang和AST(抽象语法树)开发的规则引擎,Gengine支持的语法是一种自定义的DSL,Gengine通过内置的解释器对规则文件进行解析,构建规则模型,进行相应的规则计算和数据处理。Gengine于2020年7月由哔哩哔哩(bilibili.com)授权开源。Gengine现已应用于B站风控系统、流量投放系统、AB测试、推荐平台系统等多个业务场景。
官网上给出的Gengine相比于Java领域的著名规则引擎drools优势如下:
| 对比 | drools | gengine |
|---|---|---|
| 执行模式 | 仅支持顺序模式 | 支持顺序模式、并发模式、混合模式,以及其他细分执行模式 |
| 规则编写难易程度 | 高,与java强相关 | 低,自定义简单语法,与golang弱相关 |
| 规则执行性能 | 低、无论是规则之间还是规则内部,都是顺序执行 | 高,无论是规则间、还是规则内,都支持并发执行.用户基于需要来选择合适的执行模式 |
Gengine开源地址:github.com/bilibili/ge…
环境准备
Go语言环境准备
- Go语言官网(golang.google.cn/dl/)下载安装go语言开发包
- 设置环境变量:GOROOT、GOPATH、GOPROXY、GO111MODULE:
- 执行go env命令进行测试
开发工具准备
推荐JetBrains GoLand
第三方库准备
- 在goland新建项目gengine。
- 在goland的settings中设置go mod库管理方式。
- 在src目录下新建go.mod文件。
- hello world测试程序:
package main
//库引用
import (
"fmt"
"github.com/bilibili/gengine/builder"
"github.com/bilibili/gengine/context"
"github.com/bilibili/gengine/engine"
)
//定义规则 (通过函数注入的方式,打印"hello world")
const rule = `
rule "1" "rule-des" salience 10
begin
println("hello world, gengine!")
end `
//主函数
func main(){
//初始化数据环境变量
dataContext := context.NewDataContext()
//注入println函数
dataContext.Add("println",fmt.Println)
//初始化规则
ruleBuilder := builder.NewRuleBuilder(dataContext)
//读取规则
err1 := ruleBuilder.BuildRuleFromString(rule)
fmt.Println(err1)
//初始化规则引擎
eng := engine.NewGengine()
//执行规则引擎
err2 := eng.Execute(ruleBuilder,true)
fmt.Println(err2)
}
功能
支持的规则语法
- 逻辑运算:&&、||、!、==、!=、>、>=、<、<=等。
- 四则运算:+、-、*、/、()等。
- if else条件选择。
- 预加载API。
规则文件
- 支持规则名称、描述、优先级设置。
- 支持规则注释。
- 支持@name、@id、@desc获取规则信息。
- 支持自定义变量。
- 支持报错时行号提示。
- 支持规则内调用注入的函数。
- 支持规则内conc{}语句块并发执行。
- 目前不支持web可视化编写规则文件,还需要技术人员进行手动配置。
执行模式
- 顺序模式:当指定规则优先级时,按照优先级顺序执行。
- 并发模式:不考虑优先级、各个规则并发执行。
- 混合模式:先执行优先级最高的一个,剩余的n-1个并发执行。
- 逆混合模式:先并发执行优先级最高的n-1个,都执行结束后执行最后一个。
对外API接口
- dataContext:支持注入需要在规则中使用的结构体、函数。
- ruleBuilder:与dataContext关联,支持通过字符串方式导入规则。
- engine:创建规则引擎,执行ruleBuilder关联的规则。
- GenginePoll:引擎实例池,支持在高QPS下实现高并发和线程安全。
支持的规则注入
- golang的struct结构体。(以指针方式注入)
- 基础类的map、array、slice。
- Golang编写的函数。
支持引擎池
- 类似于线程池或数据库连接池。
待整理后持续更新