Config
规则引擎实例的Config (opens new window) 是一个全局配置。可以通过以下方式修改config:
config := rulego.NewConfig()
ruleEngine, err := rulego.New("rule01", []byte(ruleChainFile), rulego.WithConfig(config))
2
# OnDebug
类型:func(flowType string, nodeId string, msg RuleMsg, relationType string, err error)
- flowType: IN/OUT,流入(IN)该组件或者流出(OUT)该组件事件类型
- nodeId: 节点ID
- msg: 消息结构体,其中消息的msg id是唯一的
- relationType: 如果flowType=IN,则代表上一个节点和该节点的连接关系,例如(True/False);如果flowType=OUT,则代表该节点和下一个节点的连接关系,例如(True/False)
- err: 错误信息
节点调试信息回调全局函数。规则链节点配置设置debugMode=true
后节点的In和Out过程都会触发。可以在该回调函数记录每个节点日志和执行情况,例如:耗时、输入消息和输出消息。
支持动态设置节点的debugMode
字段关闭或者开启。
提示
OnDebug
回调函数里面的自定义逻辑是异步触发的,无法保证执行顺序。
可视化界面参考:
# OnEnd(弃用)
弃用,使用types.WithOnEnd方式
类型:func(msg RuleMsg, err error)
- msg: 结束点组件处理后的msg
- err: 错误信息
规则链执行完成回调全局函数,如果规则链有多个结束点,则执行多次。 例如:执行s1之后同时触发了s2、s3、s4,那么onEnd事件会触发3次,msg是分别s2、s3、s4的执行结果。规则链如下图:
提示
config配置的OnEnd函数是规则链引擎实例全局的。也可以为每条消息配置结束回调函数,使用以下方式:
ruleEngine.OnMsg(msg, types.WithOnEnd(func(ctx types.RuleContext,msg types.RuleMsg, err error) {
//结束回调函数
}))
2
3
如果想在规则链处理完成后执行一次,可以使用以下方式:
ruleEngine.OnMsg(msg,types.WithOnAllNodeCompleted(func() {
//处理完成
}))
2
3
# ScriptMaxExecutionTime
类型:time.Duration
js脚本执行超时时间,默认2000毫秒。
# Pool
类型:types.Pool
协程池接口,如果不配置,则使用 go func 方式。
默认使用内置的pool.WorkerPool
。兼容ants协程池,可以使用ants协程池实现,需要自行引入对应的库。例如:
pool, _ := ants.NewPool(math.MaxInt32)
config := rulego.NewConfig(types.WithPool(pool))
2
提示
内置的pool.WorkerPool
是参考了FastHttp的实现,比ants
性能高和节省内存。
# ComponentsRegistry
类型:types.ComponentRegistry
组件库注册器,默认使用rulego.Registry
# Parser
类型:types.Parser
规则链解析接口,默认使用:rulego.JsonParser
,可以实现自定义规则链DSL。
# Logger
类型:types.Logger
日志记录接口,默认使用:DefaultLogger()
。log组件 使用该记录器。
# Properties
类型:types.Metadata
全局属性,key-value形式。
规则链节点配置可以通过${global.propertyKey}
方式替换变量的内容。
- 其中
global.
为内置变量,代表从config.Properties中获取内容进行替换(节点初始化时候执行替换逻辑,只执行一次)。使用示例参考:node_config (opens new window) - 另外JavaScript、Lua等脚本引擎都可以通过
global.propertyKey
方式获取全局属性值。
Lua脚本中调用:
var value=global.propertyKey;
Lua脚本中调用:
-- 调用全局配置参数
-- 对应JS中的: var value=global.propertyKey;
local propertyValue = global.propertyKey
2
3
# UDF
类型:map[string]interface{}
注册自定义Golang函数和原生脚本,使JavaScript/Lua等脚本引擎可以直接调用。支持两种注册方式:
# 1. Golang函数注册
支持两种注册方式:
# 1.1 直接函数注册
config := rulego.NewConfig()
// 方式1:使用types.Script包装
config.RegisterUdf("add", types.Script{
Type: types.All,//lua js脚本都能调用
Content: func(a, b int) int {
return a + b
},
})
// 方式2:直接注册函数,lua js脚本都能调用
config.RegisterUdf("handleMsg", func(msg map[string]interface{}, metadata map[string]string, msgType string) string {
msg["processed"] = true
return "processed_" + msgType
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1.2 结构体方法注册
// 定义工具结构体
type ToolTest struct {
}
// Query 结构体方法示例
func (t *ToolTest) Query(id string) string {
return "result:" + id
}
// Delete 结构体方法示例
func (t *ToolTest) Delete(id string) bool {
return true
}
// 注册结构体指针的所有导出方法
var tool = &ToolTest{}
config.RegisterUdf(
"tool", // 注册名称
tool, // 结构体指针
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2. 原生脚本注册(js)
支持直接注入JavaScript源码到脚本上下文。
// 注册JavaScript工具函数
config.RegisterUdf("utils", types.Script{
Type: types.Js,
Content: `var utilsFunc={
dateFormat:function(date,fmt){
//日期格式化逻辑
return fmt;
},
isArray:function(arg){
if (typeof Array.isArray === 'undefined') {
return Object.prototype.toString.call(arg) === '[object Array]'
}
return Array.isArray(arg)
},
isObject: function(value){
if (!data || this.isArray(data)) {
return false;
}
return data instanceof Object;
},
isNumber: function(value){
return typeof value === "number";
},
}
`,
})
//调用:let result =utilsFunc.dateFormat(new Date(), 'YYYY-MM-DD')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 3. 原生脚本注册(Lua)
支持直接注入Lua源码到脚本上下文
config.RegisterUdf("myFuncDirect", types.Script{
Type: types.Lua,
Content: "function(a, b) return a + b end", // UDF is a function definition string
})
//调用:local result = myFuncDirect(5, 6)
2
3
4
5
# 4. 注册Lua特定函数
//注册Lua自定义函数,lua脚本才能调用
config.RegisterUdf("add", types.Script{Type: types.Lua, Content: func(L *lua.LState) int {
a := L.CheckNumber(1)
b := L.CheckNumber(2)
L.Push(lua.LNumber(a + b))
return 1
}})
2
3
4
5
6
7
# JavaScript调用示例
// 调用Go注册的add函数
let sum = add(10, 20);
// 调用注册的utils工具函数
let formattedDate = utilsFunc.dateFormat(new Date(), 'YYYY-MM-DD');
let isArray = utilsFunc.isArray([1,2,3]);
// 调用结构体方法示例
let queryResult = tool.Query('1001');
let deleteStatus = tool.Delete('1001');
2
3
4
5
6
7
8
9
10
# Lua调用示例
-- 调用Go注册的add函数
local result = add(10, 20)
2
# Aspects
类型:[]Aspect
AOP 切面列表。示例:
//添加组件故障降级切面
config := rulego.NewConfig(
types.WithAspects(&aspect.SkipFallbackAspect{ErrorCountLimit: 3, LimitDuration: time.Second * 10})
)
2
3
4
# NodeClientInitNow
类型:bool
网络客户端类的组件(例如:mqtt客户端组件、kafka客户端组件等)是否在初始化时候立即初始化。 默认为false
,即在第一次调用组件时才初始化。
true
: 在初始化时候立即初始化,如果初始化失败,则规则链不会启动。false
: 在第一次调用组件时才初始化,如果初始化失败,则规则链会启动,但组件调用会失败。
# AllowCycle
类型:bool
是否允许规则链中节点存在循环依赖。默认为false
,即不允许。
# Cache
类型:types.Cache
缓存用于跨规则链之间或者同规则链实例不同执行上下文之间的数据共享,缓存级别为chain
和global
级别。
- chain: 当前规则链级别缓存,在当前规则链命名空间下操作,用于规则链实例内不同执行上下文之间的数据共享。如果规则链实例被销毁,会自动删除该规则链命名空间下所有缓存。
- global: 全局级别缓存,在全局命名空间下操作,用于跨规则链间的数据共享
框架内部会在同一个缓存实例中提供这两种级别的缓存操作。缓存的操作有以下几种方式
# js脚本中操作缓存
可以在js脚本相关组件例如:js脚本转换器 js脚本过滤器 ,通过$ctx
内置变量中获取缓存对象,并调用对应的方法进行缓存操作。
let cache=$ctx.ChainCache();//获取当前规则链级别缓存,在当前规则链命名空间下操作
//let cache=$ctx.GlobalCache();//获取全局级别缓存,在全局命名空间下操作
let err=cache.Set("key", "value");//设置缓存,永不过期
let err=cache.Set("key2", "value2","10m");//设置缓存,10分钟后过期
//设置复杂结构体
var user1={"name":"John","age":30}
$ctx.ChainCache().Set("user1", user1)
let value=cache.Get("key1");//获取缓存
let ok=cache.Has("key1");//判断缓存是否存在
let err=cache.Delete("key1");//删除缓存
let values=cache.GetByPrefix("prefix_key");//获取指定前缀的所有缓存
let err=cache.DeleteByPrefix("prefix_key");//删除指定前缀的所有缓存
2
3
4
5
6
7
8
9
10
11
12
# Lua脚本中操作缓存
可以在Lua脚本相关组件例如:lua脚本转换器 lua脚本过滤器 ,
通过ChainCache
或者GlobalCache
内置变量中获取缓存对象,并调用对应的方法进行缓存操作。
local cache = ChainCache --获取当前规则链级别缓存,在当前规则链命名空间下操作
--local cache = GlobalCache --获取全局级别缓存,在全局命名空间下操作
cache.Set('key1', 'value1') --设置缓存,永不过期
cache.Set('key2', 'value2', '10m') --设置缓存,10分钟后过期
local value = cache.Get('key1') --获取缓存
local ok = cache.Has('key1') --判断缓存是否存在
cache.Delete('key1') --删除缓存
local values = cache.GetByPrefix('prefix_key') --获取指定前缀的所有缓存
cache.DeleteByPrefix('prefix_key') --删除指定前缀的所有缓存
2
3
4
5
6
7
8
9
# RuleContext
中操作缓存
在规则引擎组件OnMsg
生命周期,可以通过RuleContext
对象获取缓存对象,并调用对应方法进行缓存操作。
cache:=ctx.ChainCache()//获取当前规则链缓存,在当前规则链命名空间下操作
//cache:=ctx.GlobalCache()//获取全局缓存,在全局命名空间下操作
err:=cache.Set("key1", "value1","0");//设置缓存,永不过期
err:=cache.Set("key2", "value2","10m");//设置缓存,10分钟后过期
v:=cache.Get("key1");//获取缓存
ok:=cache.Has("key1");//判断缓存是否存在
err:=cache.Delete("key1");//删除缓存
values:=cache.GetByPrefix("prefix_key");//获取指定前缀的所有缓存
err:=cache.DeleteByPrefix("prefix_key");//删除指定前缀的所有缓存
2
3
4
5
6
7
8
9
# 组件中操作缓存
可以通过组件操作缓存,参考:缓存获取组件、缓存删除组件、缓存设置组件
# 缓存实现配置
默认情况下,RuleGo 使用内置的本地内存缓存(utils/cache.MemoryCache
),并提供了一个全局默认实例 cache.DefaultCache
(默认GC清理周期为5分钟)。如果未通过 types.WithCache
选项指定自定义缓存实现,则系统将自动使用此默认内存缓存。
如需使用其他缓存类型(例如 Redis、Memcached 等),您需要自行实现 types.Cache
接口,并通过 types.WithCache
选项在创建 Config
时将其注入。
types.Cache
接口定义如下:
package types
// Cache 定义了缓存存储的接口
// 提供基于键值对的存储和检索功能,并支持过期时间
// 实现类必须确保线程安全
type Cache interface {
// Set 在缓存中存储一个键值对,可选设置过期时间
// 参数:
// - key:缓存键(字符串)
// - value:要存储的值(interface{})
// - ttl:存活时间字符串(例如“10m”,“1h”)
// 返回:
// - error:如果 ttl 格式无效,则返回错误
// 注意:如果 ttl 为 0 或空字符串,则该项永不过期
Set(key string, value interface{}, ttl string) error
// Get 通过键从缓存中检索值
// 参数:
// - key:要查找的缓存键(字符串)
// 返回:
// - interface{}:存储的值,如果不存在或已过期则返回 nil
Get(key string) interface{}
// Has 检查键是否存在于缓存中
// 参数:
// - key:要检查的缓存键(字符串)
// 返回:
// - bool:如果键存在且未过期,则返回 true,否则返回 false
Has(key string) bool
// Delete 通过键删除缓存项
// 参数:
// - key:要删除的缓存键(字符串)
// 返回:
// - error:当前实现始终返回 nil
Delete(key string) error
// DeleteByPrefix 删除所有具有指定前缀的缓存项
// 参数:
// - prefix:要匹配的键前缀(字符串)
// 返回:
// - error:当前实现始终返回 nil
DeleteByPrefix(prefix string) error
// GetByPrefix 检索所有键与指定前缀匹配的值
// 参数:
// - prefix:要匹配的键前缀(字符串)
// 返回:
// - map[string]interface{}:匹配的键值对映射
GetByPrefix(prefix string) map[string]interface{}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
配置示例:
// 使用自定义缓存实现
config := rulego.NewConfig(types.WithCache(&myCacheImpl{}))
// 如果使用默认内存的实现,则不需要显式配置,RuleGo会自动使用 cache.DefaultCache
// config := rulego.NewConfig()
2
3
4
5