MST

星途 面试题库

面试题:Go配置文件热加载实现

在一个Go服务程序中,要求实现配置文件的热加载功能,即配置文件修改后无需重启服务就能应用新的配置。请描述实现思路,并给出关键代码片段,说明如何优雅地处理配置变更带来的业务逻辑调整。
26.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 选择配置文件格式:常见的如JSON、YAML等,Go标准库对JSON支持良好,也可使用第三方库处理YAML等格式。
  2. 定期读取配置文件:使用Go的time.Ticker定期检查配置文件修改时间,若文件更新则重新读取。
  3. 使用通道(Channel)进行通知:当检测到配置文件更新时,通过通道通知业务逻辑,使其能及时做出调整。
  4. 实现配置结构体:定义一个结构体来表示配置信息,方便在程序中使用。

关键代码片段

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"
    "time"
)

// Config 配置结构体
type Config struct {
    ServerAddr string `json:"server_addr"`
    DatabaseDSN string `json:"database_dsn"`
    // 其他配置字段
}

var (
    config      Config
    configMutex = new(sync.RWMutex)
    configUpdate = make(chan struct{})
)

// loadConfig 加载配置文件
func loadConfig() error {
    data, err := ioutil.ReadFile("config.json")
    if err != nil {
        return err
    }
    return json.Unmarshal(data, &config)
}

// watchConfig 监控配置文件变化
func watchConfig() {
    lastModTime := time.Time{}
    for {
        fileInfo, err := os.Stat("config.json")
        if err != nil {
            fmt.Printf("Error stating config file: %v\n", err)
            time.Sleep(5 * time.Second)
            continue
        }
        if fileInfo.ModTime().After(lastModTime) {
            if err := loadConfig(); err == nil {
                fmt.Println("Config reloaded successfully")
                lastModTime = fileInfo.ModTime()
                configUpdate <- struct{}{}
            } else {
                fmt.Printf("Error reloading config: %v\n", err)
            }
        }
        time.Sleep(5 * time.Second)
    }
}

处理配置变更带来的业务逻辑调整

  1. 在业务逻辑中监听通道:在启动业务逻辑的goroutine中,监听configUpdate通道。
func main() {
    if err := loadConfig(); err != nil {
        fmt.Printf("Error loading config: %v\n", os.Exit(1))
    }

    go watchConfig()

    go func() {
        for {
            select {
            case <-configUpdate:
                configMutex.Lock()
                // 根据新的配置更新业务逻辑相关的设置,例如重新连接数据库
                fmt.Println("Updating business logic with new config")
                configMutex.Unlock()
            }
        }
    }()

    // 其他业务逻辑
    select {}
}
  1. 使用互斥锁(Mutex):由于配置可能在多个goroutine中访问,使用互斥锁保护配置结构体,确保数据一致性。在读取配置时使用读锁(RLock),在更新配置和根据新配置调整业务逻辑时使用写锁(Lock)。

通过上述方式,可以优雅地实现Go服务程序中配置文件的热加载以及对配置变更带来的业务逻辑调整。