How to use golang viper Watchconfig & onConfigChange

huangapple go评论172阅读模式
英文:

How to use golang viper Watchconfig & onConfigChange

问题

我正在尝试使用golang的viper库读取我的应用程序配置,并希望始终读取最新的配置。请查看下面的代码:

config.go

  1. package config
  2. import (
  3. "github.com/spf13/viper"
  4. "log"
  5. "github.com/fsnotify/fsnotify"
  6. "time"
  7. )
  8. type Reader interface {
  9. GetAllKeys() []string
  10. Get(key string) interface{}
  11. GetBool(key string) bool
  12. GetString(key string) string
  13. }
  14. type viperConfigReader struct {
  15. viper *viper.Viper
  16. }
  17. var TestConfReader *viperConfigReader
  18. func (v viperConfigReader) GetAllKeys() []string{
  19. return v.viper.AllKeys()
  20. }
  21. func (v viperConfigReader) Get(key string) interface{} {
  22. return v.viper.Get(key)
  23. }
  24. func (v viperConfigReader) GetBool(key string) bool {
  25. return v.viper.GetBool(key)
  26. }
  27. func (v viperConfigReader) GetString(key string) string {
  28. return v.viper.GetString(key)
  29. }
  30. func init() {
  31. v:= viper.New()
  32. v.SetConfigName("test")
  33. v.AddConfigPath("/tmp/")
  34. err := v.ReadInConfig()
  35. if err != nil {
  36. log.Panic("Not able to read configuration", err.Error())
  37. }
  38. TestConfReader = &viperConfigReader{
  39. viper: v,
  40. }
  41. go func() {
  42. for {
  43. time.Sleep(time.Second * 5)
  44. v.WatchConfig()
  45. v.OnConfigChange(func(e fsnotify.Event) {
  46. log.Println("config file changed", e.Name)
  47. })
  48. }
  49. }()
  50. }

main.go

  1. package main
  2. import (
  3. "github.com/xxxx/xxxx/config"
  4. "log"
  5. "time"
  6. )
  7. func main() {
  8. conf := config.TestConfReader
  9. log.Println(conf.GetAllKeys())
  10. log.Println(conf.GetString("test1"))
  11. time.Sleep(20 * time.Second)
  12. log.Println(conf.GetString("test1"))
  13. }

当主程序运行时,我尝试更新配置,并期望看到"OnConfigChange"的日志消息,但从未显示出来。

你可以如何修复这个程序?

有人可以提供一个使用viper的WatchConfig和OnConfigChange方法读取最新配置的示例吗?

英文:

I am trying to read my application configuration using golang viper and would like to read the latest config always. Please find my code below

config.go

  1. package config
  2. import (
  3. "github.com/spf13/viper"
  4. "log"
  5. "github.com/fsnotify/fsnotify"
  6. "time"
  7. )
  8. type Reader interface {
  9. GetAllKeys() []string
  10. Get(key string) interface{}
  11. GetBool(key string) bool
  12. GetString(key string) string
  13. }
  14. type viperConfigReader struct {
  15. viper *viper.Viper
  16. }
  17. var TestConfReader *viperConfigReader
  18. func (v viperConfigReader) GetAllKeys() []string{
  19. return v.viper.AllKeys()
  20. }
  21. func (v viperConfigReader) Get(key string) interface{} {
  22. return v.viper.Get(key)
  23. }
  24. func (v viperConfigReader) GetBool(key string) bool {
  25. return v.viper.GetBool(key)
  26. }
  27. func (v viperConfigReader) GetString(key string) string {
  28. return v.viper.GetString(key)
  29. }
  30. func init() {
  31. v:= viper.New()
  32. v.SetConfigName("test")
  33. v.AddConfigPath("/tmp/")
  34. err := v.ReadInConfig()
  35. if err != nil {
  36. log.Panic("Not able to read configuration", err.Error())
  37. }
  38. TestConfReader = &viperConfigReader{
  39. viper: v,
  40. }
  41. go func() {
  42. for {
  43. time.Sleep(time.Second * 5)
  44. v.WatchConfig()
  45. v.OnConfigChange(func(e fsnotify.Event) {
  46. log.Println("config file changed", e.Name)
  47. })
  48. }
  49. }()
  50. }

main.go

  1. package main
  2. import (
  3. "github.com/xxxx/xxxx/config"
  4. "log"
  5. "time"
  6. )
  7. func main() {
  8. conf := config.TestConfReader
  9. log.Println(conf.GetAllKeys())
  10. log.Println(conf.GetString("test1"))
  11. time.Sleep(20 * time.Second)
  12. log.Println(conf.GetString("test1"))
  13. }

When the main program is running, I tried to update the config and expected to see OnConfigChange log message but it never showed up.

How can I fix this program ?.

Can someone provide an example of using viper watchconfig & onconfigchange methods to read the latest config

答案1

得分: 3

ymonad的评论是正确的,根据你的操作系统,你可能会遇到viper/fsnotify的问题。

例如,我在Mac OS X(Sierra)上运行了你的示例代码,并注意到你描述的相同症状:当配置文件位于/tmp时,viper的WatchConfig调用不会触发viper的OnConfigChange函数。

然而,当我将AddConfigPath更改为使用当前工作目录或我的主目录时,我确实能够看到来自你的OnConfigChange函数的日志。例如,尝试一下:

  1. v.AddConfigPath("./")

我建议尝试不同的目录位置,看看这是否是viper/fsnotify的某种错误或限制。由于某种原因,在Mac OS X上,它似乎无法检测到/tmp目录中的更改,至少对于我的设置来说是这样。我在OS X上找不到关于/tmp的任何问题的提及,但是fsnotify的CONTRIBUTING.md提到了在Vagrant下的“共享”目录的限制,因此可能存在一些文件系统配置不会触发通知的情况:

> 注意:在共享文件夹中,fsnotify文件系统事件不会触发。测试通过使用/tmp目录来解决这个限制。

另外,你不需要通过goroutine不断调用WatchConfigOnConfigChange。你可以完全消除goroutine,并将相关行移到init函数中。

英文:

The comment by ymonad is on the right track, depending on your OS you may be experiencing problems with viper/fsnotify.

For example, I ran your example code on Mac OS X (Sierra) and noticed the same symptom you described: when the config file is in /tmp the viper WatchConfig call was not causing the viper OnConfigChange function to be called.

However, when I change the AddConfigPath to use the current working directory or my home directory then I do see logging from your OnConfigChange function. For example, try:

  1. v.AddConfigPath("./")

I'd recommend experimenting with different directory locations to see if this is some sort of viper/fsnotify bug or limitation. For some reason, it doesn't appear to detect changes from the /tmp directory on Mac OS X, at least, it doesn't for my setup. I couldn't find any mention of problems with /tmp on OS X, but the fsnotify CONTRIBUTING.md does mention limitations with "shared" directories under Vagrant so perhaps there are some filesystem configurations that do not trigger notifications:

> Notice: fsnotify file system events won't trigger in shared folders. The tests get around this limitation by using the /tmp directory.

Also, you don't need to keep calling WatchConfig and OnConfigChange via your goroutine. You can eliminate the goroutine completely and just move the relevant lines into init.

huangapple
  • 本文由 发表于 2017年2月5日 07:33:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/42046893.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定