🐛 fix(server): 增加优雅退出与请求超时保护
- 新增 SIGINT/SIGTERM 信号处理与 http.Server.Shutdown,退出前确保统计数据保存、数据库正常关闭 - 为 http.Server 设置 ReadHeaderTimeout/ReadTimeout/WriteTimeout/IdleTimeout,防止慢客户端长期占用连接 - 全局配置指针改为 atomic.Pointer 并提供 GetAppConfig 访问器,消除配置热更新时的数据竞争,同时删除冗余的 manager.config 字段 - 请求统计九组计数器重构为 map[string]*atomic.Int64,统一 incrementStat/getStatsSnapshot 访问,精简约 40 行样板代码 - go mod tidy 清理 go.mod 与 go.sum 中的冗余依赖条目
This commit is contained in:
1 parent
6981148727
commit
d710d382ee
12 files changed
+125
-305
No files matched your search
+18
-21
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@@ -67,17 +68,21 @@ type DeviceKeyPoolConfig struct {
|
||||
// ConfigManager 配置管理器
|
||||
type ConfigManager struct {
|
||||
mu sync.RWMutex
|
||||
config *Config
|
||||
configPath string
|
||||
callbacks []func(*Config)
|
||||
}
|
||||
|
||||
var (
|
||||
// AppConfig 全局配置实例
|
||||
AppConfig *Config
|
||||
// appConfig 全局配置实例(原子指针,热更新替换时读取侧无数据竞争)
|
||||
appConfig atomic.Pointer[Config]
|
||||
manager *ConfigManager
|
||||
)
|
||||
|
||||
// GetAppConfig 获取当前配置,未加载时返回 nil
|
||||
func GetAppConfig() *Config {
|
||||
return appConfig.Load()
|
||||
}
|
||||
|
||||
// NewConfigManager 创建配置管理器
|
||||
func NewConfigManager() *ConfigManager {
|
||||
return &ConfigManager{
|
||||
@@ -109,10 +114,7 @@ func LoadConfig(configPath string) error {
|
||||
}
|
||||
|
||||
// 更新配置
|
||||
manager.mu.Lock()
|
||||
manager.config = newConfig
|
||||
AppConfig = newConfig
|
||||
manager.mu.Unlock()
|
||||
appConfig.Store(newConfig)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -155,18 +157,11 @@ func setDefaults() {
|
||||
|
||||
// GetConfig 获取配置实例
|
||||
func GetConfig() *Config {
|
||||
if manager != nil {
|
||||
manager.mu.RLock()
|
||||
defer manager.mu.RUnlock()
|
||||
if manager.config != nil {
|
||||
return manager.config
|
||||
}
|
||||
if cfg := appConfig.Load(); cfg != nil {
|
||||
return cfg
|
||||
}
|
||||
|
||||
if AppConfig == nil {
|
||||
log.Fatal("配置未初始化,请先调用 LoadConfig")
|
||||
}
|
||||
return AppConfig
|
||||
log.Fatal("配置未初始化,请先调用 LoadConfig")
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReloadConfig 重新加载配置文件
|
||||
@@ -196,9 +191,11 @@ func ReloadConfig() error {
|
||||
|
||||
// 更新配置
|
||||
manager.mu.Lock()
|
||||
oldAlgorithm := manager.config.Fanqie.Algorithm
|
||||
manager.config = newConfig
|
||||
AppConfig = newConfig
|
||||
var oldAlgorithm string
|
||||
if old := appConfig.Load(); old != nil {
|
||||
oldAlgorithm = old.Fanqie.Algorithm
|
||||
}
|
||||
appConfig.Store(newConfig)
|
||||
callbacks := make([]func(*Config), len(manager.callbacks))
|
||||
copy(callbacks, manager.callbacks)
|
||||
manager.mu.Unlock()
|
||||
|
||||
Reference in new issue
Block a user