0%

从etcd加载配置项

从etcd加载配置项

1 目录结构

1
2
3
4
$ tree etcd/
etcd/
├── etcd_biz.go
└── etcd_conn.go
  • etcd_conn.go 存放 etcd client 初始化、获取/设置/删除、关闭连接相关的代码
  • etcd_biz.go 存放与业务逻辑相关的代码

2 etcd_conn

2.1 初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var (
client *clientv3.Client
)

func Init(endpoints []string) (err error) {
client, err = clientv3.New(clientv3.Config{
Endpoints: endpoints,
DialTimeout: time.Second * 5,
})
if err != nil {
logrus.Errorf("init etcd client error: %w", err)
return err
}
return nil
}

2.2 获取值

1
2
3
4
5
6
7
8
9
10
11
12
13
func GetValue(key string) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
resp, err := client.Get(ctx, key)
defer cancel()
if err != nil {
logrus.Errorf("get config from etcd error: %w", err)
return "", err
}
if len(resp.Kvs) == 0 {
return "", fmt.Errorf("no such entry")
}
return string(resp.Kvs[0].Value), nil
}
  • etcd v3 使用gRPC实现远程过程调用,为了确保不产生goroutine泄露(不被使用的goroutine一直占用资源),调用etcd v3 client API时,要传入context.WithTimeout参数,用于通知子goroutine结束,释放资源

2.3 关闭连接

1
2
3
4
5
6
7
8
func Close() error {
err := client.Close()
if err != nil {
logrus.Errorf("close etcd client error: %w", err)
return err
}
return nil
}

3 配置项结构

1
2
3
4
5
6
7
8
var (
CollectConfig []CollectConfigEntry
)

type CollectConfigEntry struct {
LogFilePath string `json:"log_file_path"`
Topic string `json:"topic"`
}
  • 配置信息 json 格式序列化之后以键值对的 value 字符串形式存储在 etcd 中

4 拉取配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
func GetCollectConfig() (config []CollectConfigEntry, err error) {
configStr, err := GetValue(conf.DefaultConfig.ETCD.CollectConfKey)
if err != nil {
logrus.Errorf("get collect config error: %w", err)
return nil, err
}
err = json.Unmarshal([]byte(configStr), &config)
if err != nil {
logrus.Errorf("unmarshal config str error: %w", err)
return nil, err
}
return config, nil
}
  • 全局的 []CollectConfigEntry 结构体数组对象 CollectConfig 用于存储配置信息,从 etcd 获取到配置值是 json 格式的字符串,需要调用 json.Unmarshal 反序列化后放入 CollectConfig 对象中