1.介绍
微服务框架 Kratos 提供了一个强大的配置管理模块 - config 组件,它支持加载、解析、动态更新配置。
它支持多种配置源,例如文件(JSON、YAML、TOML 等格式)、环境变量、远程配置中心(如 Apollo、Etcd)等。
2.config 组件
Kratos 的 config 组件的核心功能包括支持多种配置源、动态更新、类型安全、扩展性。
其中,类型安全是指通过结构体绑定,将配置数据加载到 Go 的结构体中;扩展性是指可以通过实现 config.Source 接口,扩展自定义配置源。
此外,它还有 config.Decoder 解析器接口,可以将配置内容解析为结构化数据;config.Loader 管理配置的核心组件,可以从多个配置源加载和合并配置。
3.配置源
我们通过示例代码,分别介绍通过 config 组件管理的多种配置源。
文件
func init() {
flag.StringVar(&flagconf, "conf", "../../configs", "config path, eg: -conf config.yaml")
}
func main() {
flag.Parse()
// 加载配置文件
c := config.New(
config.WithSource(
file.NewSource(flagconf),
),
)
defer c.Close()
// 加载配置
if err := c.Load(); err != nil {
panic(err)
}
// 获取配置
var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
panic(err)
}
// ...
}
阅读上面这段代码,我们可以发现使用 config 组件读取配置,总共需要三步,一是使用 config.New() 加载配置文件,返回一个 Config 接口,示例代码中使用 file.NewSource() 获取 blog/configs 目录中的配置文件。
// Config is a config interface.
type Config interface {
Load() error
Scan(v interface{}) error
Value(key string) Value
Watch(key string, o Observer) error
Close() error
}
二是使用 Load() 方法加载配置,也就是读取配置内容。
三是使用 Scan() 方法获取配置,也就是将配置内容解析为结构化数据。
需要注意的是,不要忘记执行 Close() 方法。
环境变量
使用 Karatos 的 config 组件读取环境变量中的配置,只需要在 config.WithSource() 方法中,添加环境变量配置源。
// 加载配置文件
c := config.New(
config.WithSource(
file.NewSource(flagconf),
env.NewSource(),
),
)
defer c.Close()
读取环境变量中的配置,一般不会使用 Scan() 方法,将获取到的配置解析到结构体中。
一般是使用 Value() 方法,直接读取键值对,例如:
// 读取环境变量
port, err := c.Value("PORT").String() // 读取环境变量 PORT
if err != nil || port == "" {
port = "8080" // 默认值
}
fmt.Println("Port:", port)
// 读取其他配置
dbHost, err := c.Value("DB_HOST").String() // 读取环境变量 DB_HOST
if err == nil {
fmt.Println("Database Host:", dbHost)
}
需要注意的是,使用 Value() 方法,读取环境变量值,key 区分大小写。
远程配置中心
我们以 apolloconfig 为例,介绍怎么使用 Kartos 的 config 组件读取远程配置中心的配置。
首先,我们需要安装依赖。
go get github.com/go-kratos/kratos/contrib/config/apollo/v2
因为 Kratos 为我们提供了读取 apolloconfig 的依赖库,所以我们只需使用依赖库初始化 apolloconfig 配置源。
// 初始化 Apollo 配置源
apolloSource := apollo.NewSource(
apollo.WithEndpoint("http://192.168.110.209:8080"), // Apollo 服务地址
apollo.WithAppID("SampleApp"), // 应用 ID
apollo.WithCluster("default"), // 集群
apollo.WithNamespace("application.properties"), // Namespace
apollo.WithEnableBackup(), // 启用本地备份
)
然后,将配置源 apolloSource,添加进去。
// 加载配置文件
c := config.New(
config.WithSource(
file.NewSource(flagconf),
env.NewSource(),
apolloSource,
),
)
最后,我们可以使用 Scan() 方法,解析到结构体中。也可以直接读取键值,此处,我们以直接读取键值为例,示例代码:
timeout, err := c.Value("application.timeout").String()
if err != nil {
panic(err)
}
fmt.Printf("timeout: %s\n", timeout)
运行项目,输出结果:
kratos run
timeout: 100
当然,我们每次修改配置时,都需要重启项目,为了避免重启项目,我们可以使用 Watch() 方法,动态监听配置变化,示例代码:
// 动态监听配置变化
err = c.Watch("application", myObserver)
if err != nil {
fmt.Println("Error watching config:", err)
return
}
阅读上面这段代码,我们可以发现 Watch() 方法的参数有 2 个,分别是 application 和 myObserver。
其中,application 是 apolloconfig 的 Namespace,myObserver 是监听函数。
// Observer 函数
func myObserver(key string, value config.Value) {
fmt.Printf("Config updated! Key: %s, New Value: %v\n", key, value.Load())
}
重新运行项目,每次修改 apolloconfig 中的配置,我们可以看到以下打印结果:
Config updated! Key: application, New Value: map[timeout:200]
4.总结
本文介绍了 Kartos 怎么使用 config 组件,读取配置。
通过示例代码,分别介绍了读取配置文件、环境变量和远程配置中心 apolloconfig 的实现方式。
当然,如果我们不想使用 Kartos 的 config 组件读取 apolloconfig 配置,而是想使用 Viper 读取 apolloconfig 配置。
可以使用 apolloconfig 的客户端 API 或三方库,比如:github.com/apolloconfig/agollo/v4,将 apolloconfig 的配置加载到 Viper 中。
限于篇幅,本文没有介绍怎么使用 Viper 读取 apolloconfig 中的配置,感兴趣的读者朋友们,可以自行尝试实现。