跳到主要内容
版本:2.9.x(Latest)

基本介绍

v2.9.5版本开始gcfg 组件新增WatcherAdapter接口, WatcherAdaptergcfg 包中的一个接口,用于实现配置文件变化监听功能。当配置文件被修改、创建、删除或权限发生变化时,注册的观察者会收到通知。

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支持

核心概念

  1. WatcherAdapter 接口:定义了添加、移除和获取观察者的方法
  2. WatcherRegistry:观察者注册管理器,提供了统一的观察者管理实现
  3. context上下文传递:通过 context 传递配置变更的详细信息

主要功能

  1. 文件监控:自动监控配置文件的变化(写入、创建、删除、重命名、权限更改)
  2. 手动触发:支持手动触发观察者回调(如 Set 操作)
  3. 并发安全:所有操作都是并发安全的
  4. 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: 数据ID
  • gcfg.ContextKeyOperation: 操作类型(继承自gcfg)
  • gcfg.ContextKeyContent: 设置的内容(继承自gcfg)

方法:

  • WithOperation(): 设置操作类型
  • WithNamespace(): 设置命名空间
  • WithGroup(): 设置组
  • WithDataId(): 设置数据ID
  • WithContent(): 设置内容
  • GetNamespace(): 获取命名空间
  • GetGroup(): 获取组
  • GetDataId(): 获取数据ID
  • GetContent(): 获取内容
  • GetOperation(): 获取操作类型

实际应用场景

  1. 动态配置更新:当配置文件被修改时,应用程序可以自动重新加载配置
  2. 日志记录:记录配置变更历史
  3. 通知机制:配置变更时通知其他组件
  4. 缓存清理:配置变更时清理相关缓存