Skip to content

配置热更新 ​

Viper 支持监听配置文件变更并实时更新。

文件监听 ​

基础监听 ​

go
package main

import (
    "log"
    "github.com/spf13/viper"
)

func main() {
    viper.SetConfigFile("config.yaml")
    viper.ReadInConfig()
    
    viper.OnConfigChange(func(e fsnotify.Event) {
        log.Printf("配置变更: %s", e.Name)
    })
    
    viper.WatchConfig()
    
    select {}
}

热更新处理器 ​

go
type Config struct {
    App struct {
        Name string `mapstructure:"name"`
        Port int    `mapstructure:"port"`
    } `mapstructure:"app"`
}

var currentConfig *Config

func main() {
    viper.SetConfigFile("config.yaml")
    viper.ReadInConfig()
    
    currentConfig = &Config{}
    viper.Unmarshal(currentConfig)
    
    viper.OnConfigChange(func(e fsnotify.Event) {
        log.Println("配置更新中...")
        viper.ReadInConfig()
        viper.Unmarshal(currentConfig)
        log.Printf("新配置: %+v", currentConfig)
    })
    
    viper.WatchConfig()
    
    startServer()
}

远程配置热更新 ​

Consul 热更新 ​

go
func watchRemoteConfig() {
    viper.AddRemoteProvider("consul", "localhost:8500", "/config/myapp")
    viper.SetConfigType("yaml")
    viper.ReadRemoteConfig()
    
    go func() {
        for {
            time.Sleep(5 * time.Second)
            if err := viper.WatchRemoteConfig(); err != nil {
                log.Printf("监听远程配置失败: %v", err)
                continue
            }
            log.Println("远程配置已更新")
        }
    }()
}

应用配置重载 ​

重载服务配置 ​

go
func reloadConfig() error {
    if err := viper.ReadInConfig(); err != nil {
        return err
    }
    
    var newConfig Config
    if err := viper.Unmarshal(&newConfig); err != nil {
        return err
    }
    
    // 更新数据库连接池
    updateDBConnection(newConfig.Database)
    
    // 更新日志级别
    updateLogLevel(newConfig.Log.Level)
    
    return nil
}

参考:https://github.com/spf13/viper