Files
goproxy/internal/config/hot_reload.go
DarkiT 7efc72b362 增加:
1.  监控指标收集
2.  中间件机制
3.  配置热更新
4.  优雅关闭
5.  插件系统
6.  API文档
7.  认证授权系统
8.  请求/响应压缩优化
2025-03-13 22:58:39 +08:00

118 lines
2.2 KiB
Go

package config
import (
"encoding/json"
"log/slog"
"os"
"path/filepath"
"sync"
"time"
"github.com/fsnotify/fsnotify"
)
// HotReloadConfig 热更新配置
type HotReloadConfig struct {
// 配置文件路径
ConfigPath string
// 配置更新回调函数
OnUpdate func(*Config)
// 配置锁
mu sync.RWMutex
// 当前配置
current *Config
// 文件监视器
watcher *fsnotify.Watcher
// 停止信号
stopChan chan struct{}
}
// NewHotReloadConfig 创建热更新配置
func NewHotReloadConfig(configPath string, onUpdate func(*Config)) (*HotReloadConfig, error) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
hrc := &HotReloadConfig{
ConfigPath: configPath,
OnUpdate: onUpdate,
watcher: watcher,
stopChan: make(chan struct{}),
}
// 加载初始配置
if err := hrc.loadConfig(); err != nil {
watcher.Close()
return nil, err
}
// 启动文件监视
go hrc.watch()
return hrc, nil
}
// loadConfig 加载配置
func (hrc *HotReloadConfig) loadConfig() error {
data, err := os.ReadFile(hrc.ConfigPath)
if err != nil {
return err
}
var config Config
if err := json.Unmarshal(data, &config); err != nil {
return err
}
hrc.mu.Lock()
hrc.current = &config
hrc.mu.Unlock()
if hrc.OnUpdate != nil {
hrc.OnUpdate(&config)
}
return nil
}
// watch 监视配置文件变化
func (hrc *HotReloadConfig) watch() {
// 添加配置文件目录到监视
configDir := filepath.Dir(hrc.ConfigPath)
if err := hrc.watcher.Add(configDir); err != nil {
slog.Error("添加配置目录到监视失败", "error", err)
return
}
for {
select {
case event := <-hrc.watcher.Events:
if event.Name == hrc.ConfigPath {
// 等待文件写入完成
time.Sleep(100 * time.Millisecond)
if err := hrc.loadConfig(); err != nil {
slog.Error("重新加载配置失败", "error", err)
}
}
case err := <-hrc.watcher.Errors:
slog.Error("配置文件监视错误", "error", err)
case <-hrc.stopChan:
hrc.watcher.Close()
return
}
}
}
// Get 获取当前配置
func (hrc *HotReloadConfig) Get() *Config {
hrc.mu.RLock()
defer hrc.mu.RUnlock()
return hrc.current
}
// Stop 停止热更新
func (hrc *HotReloadConfig) Stop() {
close(hrc.stopChan)
}