张三admin

V1

2022/10/19阅读:28主题:橙心

viper读取etcd做配置热更新

概述

项目启动肯定少不了配置文件,一般我们会放在单独的目录,例如config中,有yaml、ini、json等等格式,一般用开源的读取相应问的文件映射到结构体中。

但是当一个项目秒杀频繁控制库存和限流策略等、或者其他需要频繁的变更配置文件的时候,就需要频繁的更改代码,打包,上线。时间成本高,实效性也低。所以一般都做配置热更新。

做配置热更新的有很多consul、Firestore、etcd、也有redis等等KV存储,今天我们要讲的是viper和etcd的热更新操作

准备工作

我用的是mac m1

安装etcd

生产环境肯定就是集群,测试我们直接单机模式了

brew install etcd

启动

etcd

测试

$ etcdctl version
etcdctl version: 3.5.5
API version: 3.5

或者docker,k8s安装测试环境

viper

go get github.com/spf13/viper

使用配置文件

func configByFile(vp *viper.Viper){
 var err error
 //设置配置文件的名字
 vp.SetConfigName("config") // name of config file (without extension)
 //设置配置文件后缀
 vp.SetConfigType("json") // REQUIRED if the config file does not have the extension in the name
 //设置配置文件的路径
 vp.AddConfigPath("/Users/xxxx/Desktop/test/testCode/")   // path to look for the config file in
 vp.Set("verbose"true) // 设置默认参数
 //读取文件
 if err = vp.ReadInConfig(); err != nil {
  if _, ok := err.(viper.ConfigFileNotFoundError); ok {
   // Config file not found; ignore error if desired
   log.Fatal("not found")
  } else {
   // Config file was found but another error was produced
  }
 }

 if err = vp.Unmarshal(&conf);nil != err{
  log.Fatal("Unmarshal ",err)
 }

 fmt.Println(conf)

 //watch
 go func() {
  vp.OnConfigChange(func(e fsnotify.Event) {
   fmt.Println("Config file changed:", e.Name)
   fmt.Println(e.String())
   fmt.Println(e.Op.String())
  })
  vp.WatchConfig()
 }()
 
}

配置文件发生修改等行为时候回接收到调用回调函数,做相应的处理

etcd做配置

func configByEtcd(vp *viper.Viper){
 var err error
 if err = vp.AddRemoteProvider("etcd3""http://127.0.0.1:2379""/config/viper-test/config");err != nil {
  log.Fatal(err)
 }
 vp.SetConfigType("json")
 if err = vp.ReadRemoteConfig();err != nil {
  log.Fatal(err)
 }

 if err = vp.Unmarshal(conf);err != nil {
  log.Fatal(err)
 }

 fmt.Println("获取的配置信息 ",conf)

 //fmt.Println(vp.Get("addr"))
 //fmt.Println(vp.Get("port"))

 go watchRemoteConfig(vp)

 select {}
}

func watchRemoteConfig(vp *viper.Viper) {

 for {
  time.Sleep(time.Second * 5) // delay after each request

  // currently, only tested with etcd support
  err := vp.WatchRemoteConfig()
  if err != nil {
   log.Printf("unable to read remote config: %v", err)
   continue
  }

  // unmarshal new config into our runtime config struct. you can also use channel
  // to implement a signal to notify the system of the changes
  if err = vp.Unmarshal(&conf); nil != err{
   log.Printf("unable to read remote config: %v", err)
   continue
  }

  fmt.Println("获取的配置信息 ",conf)

 }
}

修改 ercdkeeper内容

查看结果

获取的配置信息  &{127.0.0.1 3307}
获取的配置信息  &{127.0.0.1 3307}
获取的配置信息  &{127.0.0.1 3307}
获取的配置信息  &{127.0.0.1 3306}
获取的配置信息  &{127.0.0.1 3306}
^Csignal: interrupt

可以看到改变了 就收到了

上边只是一个简单的使用,更具体的应用可以自己封装下 ,还是很实用的

分类:

后端

标签:

后端

作者介绍

张三admin
V1