Files
aiops/backend/config/config.go
T
Logan.Li 59320aa410 perf: 修复 Agent 校验 CPU 热点并实现指标分层聚合与频率下发
CPU 根因:每个 Agent 请求都做一次 bcrypt 校验(实测 72ms),
30 台主机 18 req/s × 72ms ≈ 1.35 核,实测容器 CPU 135%。

- agentauth: 校验结果按 Token 哈希缓存(TTL 5min,轮换即失效),
  last_used_at 写入按 60s 节流。实测 CPU 135% → 1.6%,请求延迟 103ms → 1.6ms
- metricagg: 新增后台逐级降采样聚合 raw→1m/5m→1h→6h/1d,取代前端手动触发
- metrics_aggregate: 补 uniq_metric_agg 唯一索引(原 idx_agg 非唯一导致 upsert 插重复行)
- agent 合并配置接口 GET /agent/config:一次返回任务+探针+端口策略+频率,
  配置轮询 5s→30s;服务端可下发 report_interval,Agent 热更新 ticker 无需重装
- retention: agent_reports 保留期 7d→1d(趋势由聚合表承担)
- redis: 增加 maxmemory 512mb + volatile-lru
- fix(upgrade): 升级脚本改为 fail-fast,修复下载失败仍报 UPGRADE_OK 的静默谎报

// Logan.Li
2026-09-14 08:23:31 +00:00

144 lines
4.8 KiB
Go

package config
import (
"fmt"
"github.com/spf13/viper"
"go.uber.org/zap"
)
// Config 应用配置
type Config struct {
Mode string `mapstructure:"mode"`
Port string `mapstructure:"port"`
LogLevel string `mapstructure:"log_level"`
Database DatabaseConfig `mapstructure:"database"`
JWT JWTConfig `mapstructure:"jwt"`
Agent AgentConfig `mapstructure:"agent"`
Retention RetentionConfig `mapstructure:"retention"`
Billing BillingConfig `mapstructure:"billing"`
Redis RedisConfig `mapstructure:"redis"`
Websocket WebsocketConfig `mapstructure:"websocket"`
}
// BillingConfig 定义云账单报告本位币及各原币种折算到 CNY 的汇率。 // Logan.Li
type BillingConfig struct {
BaseCurrency string `mapstructure:"base_currency"`
ExchangeRates map[string]float64 `mapstructure:"exchange_rates"`
}
// DatabaseConfig 数据库配置
type DatabaseConfig struct {
Driver string `mapstructure:"driver"`
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
DBName string `mapstructure:"dbname"`
Charset string `mapstructure:"charset"`
MaxConn int `mapstructure:"max_conn"`
MaxIdle int `mapstructure:"max_idle"`
}
// JWTConfig JWT配置
type JWTConfig struct {
Secret string `mapstructure:"secret"`
ExpireHour int `mapstructure:"expire_hour"`
}
// AgentConfig Agent 接入安全配置。 // Logan.Li
type AgentConfig struct {
EnforceAuth bool `mapstructure:"enforce_auth"`
}
// RetentionConfig 高频数据保留期配置,单位为天。 // Logan.Li
type RetentionConfig struct {
AgentReportsDays int `mapstructure:"agent_reports_days"`
MetricHistoryDays int `mapstructure:"metric_history_days"`
MetricAggregateDays int `mapstructure:"metric_aggregate_days"`
SNMPSamplesDays int `mapstructure:"snmp_samples_days"`
SiteResultsDays int `mapstructure:"site_results_days"`
LogEntriesDays int `mapstructure:"log_entries_days"`
CleanupBatchSize int `mapstructure:"cleanup_batch_size"`
}
// RedisConfig Redis配置
type RedisConfig struct {
Driver string `mapstructure:"driver"` // redka (内嵌) / redis (外部)
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Password string `mapstructure:"password"`
DB int `mapstructure:"db"`
}
// WebsocketConfig WebSocket配置
type WebsocketConfig struct {
ReadBufferSize int `mapstructure:"read_buffer_size"`
WriteBufferSize int `mapstructure:"write_buffer_size"`
}
// Load 加载配置
func Load() *Config {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath("./configs")
viper.AddConfigPath(".")
// 设置默认值
viper.SetDefault("mode", "development")
viper.SetDefault("port", "8080")
viper.SetDefault("log_level", "info")
viper.SetDefault("database.driver", "sqlite")
viper.SetDefault("database.dbname", "sqlite3.db")
viper.SetDefault("database.host", "localhost")
viper.SetDefault("database.port", 3306)
viper.SetDefault("database.charset", "utf8mb4")
viper.SetDefault("database.max_conn", 100)
viper.SetDefault("database.max_idle", 10)
viper.SetDefault("jwt.expire_hour", 24)
viper.SetDefault("agent.enforce_auth", false)
// 原始 Agent 上报仅作短期排障用;长期趋势由 monitor_metric_aggregates 承担,
// 故原始表保留期收敛到 1 天,避免高频表无限膨胀。 // Logan.Li
viper.SetDefault("retention.agent_reports_days", 1)
viper.SetDefault("retention.metric_history_days", 30)
viper.SetDefault("retention.metric_aggregate_days", 365)
viper.SetDefault("retention.snmp_samples_days", 30)
viper.SetDefault("retention.site_results_days", 30)
viper.SetDefault("retention.log_entries_days", 30)
viper.SetDefault("retention.cleanup_batch_size", 10000)
viper.SetDefault("billing.base_currency", "CNY")
viper.SetDefault("billing.exchange_rates.CNY", 1.0)
viper.SetDefault("billing.exchange_rates.USD", 7.2)
viper.SetDefault("redis.host", "localhost")
viper.SetDefault("redis.port", 6379)
viper.SetDefault("redis.driver", "redka")
viper.SetDefault("websocket.read_buffer_size", 1024)
viper.SetDefault("websocket.write_buffer_size", 1024)
// 读取环境变量
viper.AutomaticEnv()
var cfg Config
if err := viper.ReadInConfig(); err != nil {
zap.L().Warn("config file not found, using defaults", zap.Error(err))
}
if err := viper.Unmarshal(&cfg); err != nil {
zap.L().Fatal("failed to unmarshal config", zap.Error(err))
}
return &cfg
}
// DSN 返回数据库连接字符串
func (d *DatabaseConfig) DSN() string {
if d.Driver == "mysql" {
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True&loc=Local",
d.User, d.Password, d.Host, d.Port, d.DBName, d.Charset)
}
if d.Driver == "sqlite" {
return d.DBName
}
return ""
}