golang,go,博客,开源,编程
Viper 支持从多种来源获取配置,除了文件、环境变量、命令行标志等外,还可以通过与 etcd
集成,从 etcd
中获取配置数据。etcd
是一个高可用的分布式键值存储,通常用于存储配置和服务发现等信息。
要让 Viper 从 etcd
获取配置,你需要使用 viper
和 etcd
的集成。虽然 Viper 本身没有直接内置 etcd
的支持,但我们可以通过一个简单的步骤将它们结合起来。
viper
用于加载配置。etcd
客户端用于从 etcd
获取配置。go get github.com/spf13/viper
go get go.etcd.io/etcd/clientv3
etcd
etcd
客户端来连接 etcd
,然后通过 Viper 加载从 etcd
获取的配置。以下是一个示例,展示如何从 etcd
获取配置并使用 Viper 管理这些配置。
package main
import (
"context"
"fmt"
"log"
"github.com/spf13/viper"
"go.etcd.io/etcd/clientv3"
"time"
)
func main() {
// 创建一个 etcd 客户端
client, err := clientv3.New(clientv3.Config{
Endpoints: []string{"localhost:2379"}, // etcd 地址
DialTimeout: 5 * time.Second,
})
if err != nil {
log.Fatal(err)
}
defer client.Close()
// 从 etcd 获取配置
kv := clientv3.NewKV(client)
resp, err := kv.Get(context.Background(), "config/app", clientv3.WithPrefix()) // 获取 "config/app" 路径下的所有配置
if err != nil {
log.Fatal(err)
}
// 将 etcd 获取到的配置加载到 viper
for _, kvPair := range resp.Kvs {
// 假设 key 是以 "config/app" 开头的,我们将去掉这个前缀
key := string(kvPair.Key)[len("config/"):]
// 使用 Viper 设置配置项
viper.Set(key, string(kvPair.Value))
}
// 输出从 etcd 获取的配置
appName := viper.GetString("app.name")
port := viper.GetInt("app.port")
fmt.Printf("App Name: %s\n", appName)
fmt.Printf("App Port: %d\n", port)
// 可以动态更新配置,监控 etcd 配置变化
watchConfig(client)
}
// watchConfig 监控 etcd 配置变化
func watchConfig(client *clientv3.Client) {
rch := client.Watch(context.Background(), "config/app", clientv3.WithPrefix())
for wresp := range rch {
for _, ev := range wresp.Events {
fmt.Printf("Event type: %s, key: %s, value: %s\n", ev.Type, ev.Kv.Key, ev.Kv.Value)
// 可以将新的配置加载到 viper
viper.Set(string(ev.Kv.Key), string(ev.Kv.Value))
}
}
}
clientv3.New
方法连接到 etcd
,EndPoints
是 etcd
的地址列表。你可以通过 DialTimeout
配置超时时间。etcd
获取配置
clientv3.NewKV(client)
创建 KV
操作对象,然后通过 kv.Get
从 etcd
获取配置。clientv3.WithPrefix()
表示获取 config/app
路径下所有的配置项。viper.Set(key, value)
将从 etcd
获取的配置动态加载到 Viper 中。etcd
中的配置信息映射到 Viper 的键值对中。etcd
配置变化
client.Watch
来监控 etcd
中 config/app
路径下的配置变化,若配置发生变化,Viper 会自动更新。viper.GetString
和 viper.GetInt
等方法来获取配置。假设你在 etcd
中存储了如下配置:
etcdctl put config/app.name "MyApp"
etcdctl put config/app.port "8080"
运行上面的 Go 程序后,Viper 会从 etcd
获取并打印出配置:
App Name: MyApp
App Port: 8080
通过调用 client.Watch
,你可以实时监控 etcd
中的配置变化。当配置发生变化时,程序会打印出变化的内容,并自动更新 viper
中的配置。
例如,假设你修改了 etcd
中的配置:
etcdctl put config/app.name "NewApp"
etcdctl put config/app.port "9090"
程序会捕获到这个变化并打印:
Event type: PUT, key: config/app.name, value: NewApp
Event type: PUT, key: config/app.port, value: 9090
etcd
中获取配置,虽然它没有直接支持 etcd
,但通过 clientv3
库获取配置,然后将配置加载到 Viper 中,依然可以实现强大的配置管理。etcd
的 Watch
功能,可以实时更新配置,并让 Viper 动态加载新的配置,支持热加载。