Go

【go】webアプリでサーバーを止めずにconfigファイルをリロードする

More than 1 year has passed since last update.


やりたいこと

webサーバー起動時にconfigファイルを読み込んでstructに入れていたが、

これだとconfigファイルに変更があった場合プロセスを再起動する必要がある。

そうではなく、変更があった場合はプロセスを止めずに自動でリロードするようにしたい。


方法

fsnotifyというライブラリを使う。

ファイルの変更などを検知してくれるので、変更がった場合に再度読み込むようにする。


ソース


config.toml

name = "fuku"

age = 20


main.go

package main

import (
"github.com/BurntSushi/toml"
"github.com/fsnotify/fsnotify"
"github.com/gin-gonic/gin"
)

type Config struct {
Name string
Age int
}

const File = "./config.toml"

var config Config

func main() {
watchConfig(&config)
r := gin.Default()
r.GET("/config", func(c *gin.Context) {
c.JSON(200, gin.H{
"name": config.Name,
"age": config.Age,
})
})
r.Run()
}

func watchConfig(conf *Config) {
reload(conf)
go monitor(conf)
}

func reload(conf *Config) {
_, err := toml.DecodeFile(File, &conf)
if err != nil {
panic(err)
}
}

func monitor(conf *Config) {
var err error
watcher, _ := fsnotify.NewWatcher()
defer watcher.Close()
for {
err = watcher.Add(File)
if err != nil {
panic(err)
}
select {
case <-watcher.Events:
reload(conf)
if err != nil {
panic(err)
}
}
}
}



確認

サーバーをたちあげてリクエストしてみる

$ go run main.go

$ curl http://localhost:8080/config
{"age":20,"name":"fuku"}

config.tomlを修正して再度リクエスト


config.toml

name = "tarou"

age = 17

$ curl http://localhost:8080/config

{"age":17,"name":"tarou"}

webサーバーを再起動しなくとも内容が変更されている確認できた。


まとめ

実際の運用でもプログラムの内容は変えずconfigだけを変更というケースは多いはず

そんな場合でもプロセスを止めずに変更を反映できるのは便利なので実施してましょう