kratos集成etcd配置中心

在kratos项目中使用etcd有两种方式

一种是使用kratos官方集成好的etcd客户端进行使用,还有一种是自己集成,下面我使用自定义的集成方式来实现配置的动态变化。

go 复制代码
type EtcdSource struct {
	client *clientv3.Client
	key    string
}

func NewEtcdSource(endpoints []string, key string) config.Source {
	cli, err := clientv3.New(clientv3.Config{
		Endpoints:   endpoints,
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		log.Fatalf("failed to connect to etcd: %v", err)
	}
	return &EtcdSource{client: cli, key: key}
}

func (s *EtcdSource) Load() ([]*config.KeyValue, error) {
	resp, err := s.client.Get(context.Background(), s.key)
	if err != nil {
		return nil, err
	}
	if len(resp.Kvs) == 0 {
		log.Infof("key %s not found during load", s.key)
		return nil, nil
	}
	return []*config.KeyValue{{
		Key:    s.key,
		Value:  resp.Kvs[0].Value,
		Format: "yaml",
	}}, nil
}

这个是读取指定key的etcd数据,实现 config.Source 还需要一个watch方法

go 复制代码
func (s *EtcdSource) Watch() (config.Watcher, error) {
    return NewEtcdWatcher(s.client, s.key), nil
}

具体的监听key的变化代码:

go 复制代码
type EtcdWatcher struct {
    client *clientv3.Client
    key    string
    ch     clientv3.WatchChan
    once   sync.Once
}

func NewEtcdWatcher(client *clientv3.Client, key string) config.Watcher {
    w := &EtcdWatcher{
       client: client,
       key:    key,
       ch:     client.Watch(context.Background(), key),
    }
    log.Infof("start watching key: %s", key)
    return w
}

func (w *EtcdWatcher) Next() ([]*config.KeyValue, error) {
    log.Infof("waiting for events on key: %s", w.key)
    var kvs []*config.KeyValue

    // 第一次调用时返回当前值
    w.once.Do(func() {
       resp, err := w.client.Get(context.Background(), w.key)
       if err != nil {
          log.Infof("failed to get initial value: %v", err)
          return
       }
       if len(resp.Kvs) > 0 {
          kvs = append(kvs, &config.KeyValue{
             Key:    w.key,
             Value:  resp.Kvs[0].Value,
             Format: "yaml",
          })
       }
    })

    if len(kvs) > 0 {
       log.Infof("returning initial value for key: %s", w.key)
       return kvs, nil
    }

    // 监听后续变化
    wr := <-w.ch
    if wr.Canceled {
       log.Infof("watch canceled: %v", wr.Err())
       return nil, wr.Err()
    }
    log.Infof("received watch events: %d", len(wr.Events))
    for _, ev := range wr.Events {
       log.Infof("event type: %v, key: %s, value: %s", ev.Type, ev.Kv.Key, ev.Kv.Value)
       if ev.Type == clientv3.EventTypePut {
          kvs = append(kvs, &config.KeyValue{
             Key:    w.key,
             Value:  ev.Kv.Value,
             Format: "yaml",
          })
       }
    }
    return kvs, nil
}
func (w *EtcdWatcher) Stop() error {
    return w.client.Close()
}

具体的使用是

go 复制代码
func InitConfig() *conf.Bootstrap {

    key := "/config/rwService"
    source := r1.NewEtcdSource([]string{"localhost:4000"}, key)
    c := config.New(config.WithSource(source))
    defer c.Close()
    if err := c.Load(); err != nil {
       log.Fatalf("failed to load config: %v", err)
    }

    var cfg conf.Bootstrap
    if err := c.Scan(&cfg); err != nil {
       log.Fatalf("failed to scan config: %v", err)
    }

    w, err := source.Watch()
    if err != nil {
       log.Fatalf("failed to watch: %v", err)
    }
    defer func() {
       if err := w.Stop(); err != nil {
          log.Error("failed to stop watcher: %v", err)
       }
    }()

    for {
       select {
       default:
          kvs, err := w.Next()
          if err != nil {
             log.Fatalf("next error: %v", err)
          }
          if len(kvs) == 0 {
             log.Infof("no events received, continuing")
             continue
          }
          for _, kv := range kvs {
             log.Infof(">>> key: %s, value: %s", kv.Key, string(kv.Value))
          }
       }
    }
    return &cfg

}

以上就实现了etcd监听配置中心的key变化实时获取数据。 也可以从官方使用数据来监听数据

arduino 复制代码
go get github.com/go-kratos/kratos/contrib/config/etcd/v2
相关推荐
liangbm315 小时前
AI-ViewNote:把网课和会议视频自动卷成结构化笔记
ai·typescript·go·软件构建·开源软件·react·桌面软件
我叫黑大帅17 小时前
Gin 实战入门:从环境搭建到企业级常用特性全解析
后端·面试·go
我叫黑大帅17 小时前
Gin 日志体系详解
后端·面试·go
F1FJJ18 小时前
Shield CLI v0.3.3 新增 PostgreSQL 插件:浏览器里管理 PG 数据库
网络·网络协议·docker·postgresql·容器·go
mCell1 天前
【万字长文】从 AI SDK 到 mini-opencode:一次很巧的 Go Agent 架构实践
架构·go·agent
jump_jump1 天前
深入理解 Go Context:从原理到实战(基于 Go 1.26)
go·源码
哈里谢顿1 天前
golang目前遇到的面试题
go
哈里谢顿1 天前
python与golang性能差异对比
go
前端Hardy2 天前
Wails v3 正式发布:用 Go 写桌面应用,体积仅 12MB,性能飙升 40%!
前端·javascript·go
golang学习记3 天前
Go 语言生产环境必备包清单
go