在实际的编程过程中,一个daemon进程通常会有一个配置文件,deamon进程根据配置文件中的配置来决定自身的行为方式;当你要改变daemon进程的行为的时候,就要改变配置文件;但是如果是一个在线的服务,同时期望是能够在不重启进程的情况下来识别配置文件的改动从而实现行为方式的改变,因为这样对系统和业务的影响最小;那该如何实时的感知配置文件的变化呢;
通常会有两种方式:
1. 定期的轮询;
2. linux提供了inotify机制;
相对来讲,轮询的方式比较容易实现,本文主要是着重看下inotify的实现机制,用到的第三方库是 github.com/fsnotify/fsnotify,示例代码如下:
package main
import "fmt"
import "sync"
import "github.com/fsnotify/fsnotify"
func main() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
fmt.Println("watcher error")
}
defer watcher.Close()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
fmt.Printf("event type:%s\n", event.Op)
fmt.Printf("file name:%#v\n", event.Name)
case err, ok := <-watcher.Errors:
if !ok {
return
}
fmt.Println(err.Error())
}
}
wg.Done()
}()
err = watcher.Add("/Users/xxx/Documents")
if err != nil {
fmt.Println(err.Error())
}
wg.Wait()
}
fsnotify对配置文件的监控类型共有:Create,Write,Remove,Rename,Chmod几种。可以监控目录(监控目录中的文件的变化)和文件;当你监控目录变化的时
inotify与轮询相比较的话, 实时性会更好一些,但也inotify对内核的版本会有一定的要求,太老的内核不支持;
当然实际的工作中也可以尝试将两者结合起来使用;
ticker := time.NewTicker(5 * time.Second)
for {
select {
case <- ticker.C:
//reload config file
case events, ok <- watcher.Events:
//reload config file
}
}