从零开始Go语言ⅩⅣ | 青训营笔记

338 阅读3分钟

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

前言
对于规则引擎的初次接触了解,以B站开源的gengine规则引擎为对象。

简介

  Gengine是一款基于golang和AST(抽象语法树)开发的规则引擎,Gengine支持的语法是一种自定义的DSL,Gengine通过内置的解释器对规则文件进行解析,构建规则模型,进行相应的规则计算和数据处理。Gengine于2020年7月由哔哩哔哩(bilibili.com)授权开源。Gengine现已应用于B站风控系统、流量投放系统、AB测试、推荐平台系统等多个业务场景。

官网上给出的Gengine相比于Java领域的著名规则引擎drools优势如下:

对比droolsgengine
执行模式仅支持顺序模式支持顺序模式、并发模式、混合模式,以及其他细分执行模式
规则编写难易程度高,与java强相关低,自定义简单语法,与golang弱相关
规则执行性能低、无论是规则之间还是规则内部,都是顺序执行高,无论是规则间、还是规则内,都支持并发执行.用户基于需要来选择合适的执行模式

Gengine开源地址:github.com/bilibili/ge…

环境准备

Go语言环境准备

  1. Go语言官网(golang.google.cn/dl/)下载安装go语言开发包
  2. 设置环境变量:GOROOT、GOPATH、GOPROXY、GO111MODULE:
  3. 执行go env命令进行测试

开发工具准备

推荐JetBrains GoLand

第三方库准备

  1. 在goland新建项目gengine。
  2. 在goland的settings中设置go mod库管理方式。
  3. 在src目录下新建go.mod文件。
  4. 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编写的函数。

支持引擎池

  • 类似于线程池或数据库连接池。

待整理后持续更新