[转载] Golang hot configuration reload

原文:http://openmymind.net/Golang-Hot-Configuration-Reload/

Like most,I've always appreciated a software package that lets me hot-reload the configuration without having to restart. Nginx immediately comes to mind,as does Postgresql (not for all settings,but most). This is something I've never done; so I was pretty happy when the opportunity presented itself.

I'm not sure how anyone else does this,but it's pretty basic stuff. When you get past the meaningless fact that you're reloading a configuration,it's just about providing concurrent read and write access to a shared object. There are a lot of ways to do that and a lot will depend on your language/framework. In Go,our approach was to use a read/write mutex.

First,our basic configuration structure,a global (to the package) variable and a similar lock:

goimport (
  "os"
  "log"
  "sync"
  "syscall"
  "os/signal"
  "io/IoUtil"
  "encoding/json"
)

type Config struct {
  Mode string
  CacheSize int
}

var (
  config *Config
  configLock = new(sync.RWMutex)
)

Next we need a function that loads our config:

gofunc loadConfig(fail bool){
  file,err := IoUtil.ReadFile("config.json")
  if err != nil {
    log.Println("open config: ",err)
    if fail { os.Exit(1) }
  }

  temp := new(Config)
  if err = json.Unmarshal(file,temp); err != nil {
    log.Println("parse config: ",err)
    if fail { os.Exit(1) }
  }
  configLock.Lock()
  config = temp
  configLock.Unlock()
}

Whether we exit on failure depends on whether this is the first time loading the configuration or if it's a reload. We use a temp variable to hold our new reference so that we can minimize the duration of our write lock to the simplist possible code.

Next we need is a way to access the current configuration:

gofunc GetConfig() *Config {
  configLock.RLock()
  defer configLock.RUnlock()
  return config
}

Finally we need to do an initial load as well as be able to cause a reload. To do this,we listen for a signal:

go// go calls init on start
func init() {
  loadConfig(true)
  s := make(chan os.Signal,1)
  signal.Notify(s,syscall.SIGUSR2)
  go func() {
    for {
      <-s
      loadConfig(false)
      log.Println("Reloaded")
    }
  }()
}

Like I said,not hard but at least a little neat.

相关文章

什么是Go的接口? 接口可以说是一种类型,可以粗略的理解为他...
1、Golang指针 在介绍Golang指针隐式间接引用前,先简单说下...
1、概述 1.1&#160;Protocol buffers定义 Protocol buffe...
判断文件是否存在,需要用到"os"包中的两个函数: os.Stat(...
1、编译环境 OS :Loongnix-Server Linux release 8.3 CPU指...
1、概述 Golang是一种强类型语言,虽然在代码中经常看到i:=1...