基本介绍
从v2.9.5版本开始gcfg 组件新增WatcherAdapter接口, WatcherAdapter 是 gcfg
包中的一个接口,用于实现配置文件变化监听功能。当配置文件被修改、创建、删除或权限发生变化时,注册的观察者会收到通知。
GoFrame 的配置监听功能为应用程序提供了动态响应配置变化的能力,使系统能够实时调整行为而无需重启。通过灵活的监听器机制和丰富的上下文信息,开发者可以轻松构建自适应的应用程序。
接口定义
https://github.com/gogf/gf/blob/master/os/gcfg/gcfg_adaper.go
// WatcherAdapter is the interface for configuration watcher.
type WatcherAdapter interface {
// AddWatcher adds a watcher function for specified `pattern` and `resource`.
AddWatcher(name string, fn func(ctx context.Context))
// RemoveWatcher removes the watcher function for specified `pattern` and `resource`.
RemoveWatcher(name string)
// GetWatcherNames returns all watcher names.
GetWatcherNames() []string
}
适配器适配情况:
| 适配器名称 | 是否支持监听回调 |
|---|---|
AdapterFile | 支持 |
AdapterContent | 支持 |
polaris | 支持 |
nacos | 支持 |
apollo | 支持 |
consul | 支持 |
kubecm | 支持 |
核心概念
WatcherAdapter接口:定义了添加、移除和获取观察者的方法WatcherRegistry:观察者注册管理器,提供了统一的观察者管理实现context上下文传递:通过context传递配置变更的详细信息
主要功能
文件监控:自动监控配置文件的变化(写入、创建、删除、重命名、权限更改)手动触发:支持手动触发观察者回调(如Set操作)并发安全:所有操作都是并发安全的panic 防护:每个观察者的执行都在独立的goroutine中,并有panic恢复机制
使用方法
让我通过示例代码展示如何使用 WatcherAdapter 功能:
1. 文件适配器的观察者使用
// 创建配置适配器
c, err := gcfg.NewAdapterFile("config.toml")
if err != nil {
panic(err)
}
// 添加观察者
c.AddWatcher("my-watcher", func(ctx context.Context) {
// 获取文件操作上下文信息
fileCtx := gcfg.GetAdapterFileCtx(ctx)
fmt.Printf("操作类型: %s\n", fileCtx.GetOperation())
fmt.Printf("文件名: %s\n", fileCtx.GetFileName())
fmt.Printf("文件路径: %s\n", fileCtx.GetFilePath())
// 根据不同操作类型处理
switch fileCtx.GetOperation() {
case gcfg.OperationWrite:
fmt.Println("配置文件被修改了")
case gcfg.OperationSet:
fmt.Printf("配置项 %s 被设置为 %v\n", fileCtx.GetKey(), fileCtx.GetValue())
}
})
// 修改配置会触发观察者
c.Set("key", "new-value")
2. 内容适配器的观察者使用
// 创建内容适配器
content := `{"key": "value"}`
adapter, err := gcfg.NewAdapterContent(content)
if err != nil {
panic(err)
}
// 添加观察者
adapter.AddWatcher("content-watcher", func(ctx context.Context) {
contentCtx := gcfg.GetAdapterContentCtx(ctx)
fmt.Printf("内容操作: %s\n", contentCtx.GetOperation())
})
// 设置新内容会触发观察者
adapter.SetContent(`{"key": "new-value"}`)
3. 与 gcfg.Config 实例一起使用
// 创建配置实例
config := g.Cfg()
// 添加观察者到配置实例的适配器
if adapter, ok := config.GetAdapter().(gcfg.WatcherAdapter); ok {
adapter.AddWatcher("config-watcher", func(ctx context.Context) {
fmt.Println("配置发生了变化")
})
}
观察者上下文信息
根据不同适配器类型,可以通过相应的上下文获取不同的信息,具体可以参考不同类型适配器的xxxAdapterCtx实现。
例如nacos可以通过adapterCtx := nacos.GetAdapterCtx(ctx)获取*NacosAdapterCtx
位于: contrib/config/nacos/nacos_adapter_ctx.go
上下文键常量:
ContextKeyNamespace: 命名空间ContextKeyGroup: 组ContextKeyDataId: 数据IDgcfg.ContextKeyOperation: 操作类型(继承自gcfg)gcfg.ContextKeyContent: 设置的内容(继承自gcfg)
方法:
WithOperation(): 设置操作类型WithNamespace(): 设置命名空间WithGroup(): 设置组WithDataId(): 设置数据IDWithContent(): 设置内容GetNamespace(): 获取命名空间GetGroup(): 获取组GetDataId(): 获取数据IDGetContent(): 获取内容GetOperation(): 获取操作类型
实际应用场景
动态配置更新:当配置文件被修改时,应用程序可以自动重新加载配置日志记录:记录配置变更历史通知机制:配置变更时通知其他组件缓存清理:配置变更时清理相关缓存