LoginSignup
9
7

More than 5 years have passed since last update.

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

Posted at

やりたいこと

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だけを変更というケースは多いはず
そんな場合でもプロセスを止めずに変更を反映できるのは便利なので実施してましょう

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7