浅谈Golang如何使用Viper进行配置管理

2023-12-05 0 1,014
目录
  • 前言
  • 配置层级
    • 0. 配置结构
    • 1. 命令行参数
    • 2. 环境变量
    • 3. 本地配置文件
    • 4. 远程配置文件
    • 5. 默认值
  • 配置动态更新
    • 1. 更新配置源中的配置
    • 2. 更新内存中的配置
    • 3. 配置的动态生效
  • 总结

    前言

    应用程序里要用到很多配置,比如监听端口、数据库相关配置、缓存相关配置等。这些配置可能来自不同的源,最常见的是本地配置文件,也可以作为命令行参数或环境变量传入,还可以托管在远程配置中心。同一项配置可能在多个不同的配置源中同时存在,如何处理优先级?在程序运行过程中,有些配置需要能够动态更新,又该如何实现?配置的源、优先级及动态更新,就是配置管理的内容。

    在Golang生态中,Viper是一个不错的开源配置管理框架。

    配置层级

    Viper支持多种配置源,并处理了它们之间的优先级问题,按优先级从高到低的顺序,层级如下:

    • 命令行参数
    • 环境变量
    • 本地配置文件
    • 远程配置文件
    • 默认值

    下面分别看一下Viper是如何支持这些配置源的。

    0. 配置结构

    以如下的yaml格式配置文件来说明:

    # myconfig.yaml
    aaa: foo
    xxx:
    bbb: bar
    ccc: 100

    Viper在内存中是用map类型来维护配置的,以配置名作为key、配置值作为Value。

    为方便使用,我们可以定义如下的结构体来接收配置:

    package config
    var Config config
    type config struct {
    Aaa string
    Xxx struct {
    Bbb string
    Ccc uint
    }
    }

    1. 命令行参数

    Viper提供了BindPFlags函数来绑定命令行参数,以Cobra命令行框架为例,初始化代码如下:

    // 1. 根据需要定义命令行参数
    pflags = rootCmd.PersistentFlags()
    pflags.StringP(\”aaa\”, \”a\”, \”\”, \”aaa\’s usage\”)
    pflags.String(\”xxx.bbb\”, \”\”, \”xxx.bbb\’s usage\”)
    pflags.Uint(\”xxx.ccc\”, 0, \”xxx.ccc\’s usage\”)
    // 2. Viper绑定命令行参数
    viper.BindPFlags(pflags)

    这样就可以通过命令行参数来传入相关配置:

    // 参数aaa使用长参数格式
    $ mycmd –aaa foo –xxx.bbb bar –xxx.ccc 100
    // 参数aaa使用短参数格式
    $ mycmd -a foo –xxx.bbb bar –xxx.ccc 100

    2. 环境变量

    Viper提供了AutomaticEnv函数来从环境变量中加载配置,示例代码如下:

    // 设置环境变量的前缀
    viper.SetEnvPrefix(\”MYCMD\”)
    // 将配置Key中的点号(.)和横杠(-)替换为下划线(_)
    viper.SetEnvKeyReplacer(strings.NewReplacer(\”.\”, \”_\”, \”-\”, \”_\”))
    // 从环境变量中读取匹配的配置
    viper.AutomaticEnv()

    这样就可以通过环境变量来传入相关配置:

    $ MYCMD_AAA=foo MYCMD_XXX_BBB=bar MYCMD_XXX_CCC=100 mycmd

    3. 本地配置文件

    Viper提供了从本地配置文件加载配置的方法,示例代码如下:

    // 在初始化cobra时,将本地配置文件路径定义为命令行参数
    pflags.StringVarP(&cfgFile, \”config\”, \”c\”, \”\”, \”config file\”)
    // 在初始化viper时,设置本地配置文件路径
    viper.SetConfigFile(cfgFile)
    // 读取本地配置文件
    if err := viper.ReadInConfig(); err != nil {
    log.Fatal(err)
    }

    这样就可以通过本地配置文件来传入相关配置:

    // myconf.yaml为同目录下的配置文件,内容如上文所述
    $ mycmd –config myconf.yaml

    4. 远程配置文件

    Viper还支持将配置文件托管在远程配置中心,如etcd,示例代码如下:

    // 注意:在实际项目中,以下参数也可以作为配置传入
    provider := \”etcd3\”
    endpoint := \”x.x.x.x:2379\”
    path := \”/config/mycmd/myconf.yaml\”
    viper.AddRemoteProvider(provider, endpoint, path)
    viper.SetConfigType(\”yaml\”)
    if err := viper.ReadRemoteConfig(); err != nil {
    log.Println(\”Read remote config failed:\”, err)
    }

    只要将myconf.yaml配置文件上传到etcd的指定路径下,程序就可以远程读取了。

    $ cat myconf.yaml | etcdctl put /config/mycmd/myconf.yaml

    5. 默认值

    Viper还支持设置默认值,对于在以上所有源中都不存在的配置,将使用其默认值,示例代码如下:

    viper.SetDefault(\”aaa\”, \”foo\”)
    viper.SetDefault(\”xxx.bbb\”, \”bar\”)
    viper.SetDefault(\”xxx.ccc\”, 100)

    在所有配置源都加载后,我们可以将Viper配置装载到配置结构体变量中,方便使用:

    if err := viper.Unmarshal(&config.Config); err != nil {
    log.Fatal(\”Viper unmarshal failed:\”, err)
    }

    配置动态更新

    以上解决了静态配置管理的问题,如何实现配置的动态更新呢?

    配置的动态更新包括三个步骤:

    • 更新配置源中的配置
    • 更新内存中的配置
    • 配置的动态生效

    注意:如Viper官方文档所提,Viper本身不是并发安全的,在实现配置动态更新时,要注意采用锁机制等方式来保证Viper并发读写的安全。

    1. 更新配置源中的配置

    在Viper支持的配置源中,命令行参数、环境变量是在进程启动时一次性读取的,不支持动态更新。本地配置文件和远程配置文件可以支持动态更新,直接修改配置文件即可。

    2. 更新内存中的配置

    Viper支持监听本地配置文件的变化,同时允许注册文件变化时的回调函数,借助这个功能可以实现本地配置文件的动态更新,示意代码如下:

    viper.OnConfigChange(func(e fsnotify.Event) {
    // 回调函数
    // 可在此处更新内存中的本地配置:
    // 1. 重新读取本地配置:ReadInConfig
    // 2. 装载到配置结构体:Unmarshal
    // 注意:为Viper及配置结构体加锁
    })
    viper.WatchConfig()

    对于远程配置文件,可以通过周期性地重新读取来实现动态更新,示意代码如下:

    go func() {
    for {
    time.Sleep(time.Second * 10)
    // 周期为10s
    // 可在此处更新内存中的远程配置:
    // 1. 重新读取远程配置:WatchRemoteConfig
    // 2. 装载到配置结构体:Unmarshal
    // 注意:为Viper及配置结构体加锁
    }
    }()

    3. 配置的动态生效

    不同配置的使用方式不同,动态生效方式也就不同,大概可以分为两类:

    • 有些配置,每次使用时都是读取最新的值,因此只要更新了内存中的配置,就会即时生效
    • 有些配置,比如数据库凭据,可能需要重建连接池才能生效

    在这里就不再细说了。

    总结

    本文介绍了在Golang中优雅、灵活地实现配置管理的一种方式,涵盖配置的源、优先级及动态更新等内容。重点说明了命令行参数、环境变量、本地配置文件、远程配置文件等多种配置源的实现方法,以及配置动态更新的实现思路。

    以上就是浅谈Golang如何使用Viper进行配置管理的详细内容,更多关于Go Viper配置管理的资料请关注悠久资源网其它相关文章!

    您可能感兴趣的文章:

    • Go语言配置解析库viper的使用指南
    • Go项目配置管理神器之viper的介绍与使用详解
    • Golang配置解析神器go viper使用详解
    • Golang使用第三方包viper读取yaml配置信息操作
    • golang常用库之配置文件解析库-viper使用详解
    • 使用Viper处理Go应用程序的配置方法

    收藏 (0) 打赏

    感谢您的支持,我会继续努力的!

    打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
    点赞 (0)

    悠久资源 Golang 浅谈Golang如何使用Viper进行配置管理 https://www.u-9.cn/jiaoben/golang/101661.html

    常见问题

    相关文章

    发表评论
    暂无评论
    官方客服团队

    为您解决烦忧 - 24小时在线 专业服务