No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

config.go 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. package config
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "sync"
  7. "gopkg.in/yaml.v2"
  8. )
  9. // ==================== 配置结构体定义 ====================
  10. // Config 应用配置
  11. type Config struct {
  12. Database DBConfig `yaml:"database"`
  13. Redis RedisConfig `yaml:"redis"`
  14. Doris DorisConfig `yaml:"doris"`
  15. RabbitMQ RabbitMQConfig `yaml:"rabbitmq"`
  16. Auth Auth `yaml:"auth"`
  17. Service Service `yaml:"service"`
  18. HTTP HTTPConfig `yaml:"http"`
  19. Micro MicroConfig `yaml:"micro"` // Go Micro配置
  20. }
  21. // ==================== 各个组件的配置结构 ====================
  22. // RabbitMQConfig RabbitMQ配置
  23. type RabbitMQConfig struct {
  24. Host string `yaml:"host"`
  25. Port int `yaml:"port"`
  26. Username string `yaml:"username"`
  27. Password string `yaml:"password"`
  28. Vhost string `yaml:"vhost"`
  29. UseTLS bool `yaml:"use_tls"`
  30. CACert string `yaml:"ca_cert"`
  31. CertFile string `yaml:"cert_file"`
  32. KeyFile string `yaml:"key_file"`
  33. MaxOpenChannels int `yaml:"max_open_channels"`
  34. ReconnectDelay int `yaml:"reconnect_delay"`
  35. MaxReconnectAttempts int `yaml:"max_reconnect_attempts"`
  36. Heartbeat int `yaml:"heartbeat"`
  37. ChannelSize int `yaml:"channel_size"`
  38. DefaultExchange string `yaml:"default_exchange"`
  39. DefaultQueue string `yaml:"default_queue"`
  40. AutoAck bool `yaml:"auto_ack"`
  41. Mandatory bool `yaml:"mandatory"`
  42. Immediate bool `yaml:"immediate"`
  43. PrefetchCount int `yaml:"prefetch_count"`
  44. PrefetchSize int `yaml:"prefetch_size"`
  45. Global bool `yaml:"global"`
  46. PublisherConfirms bool `yaml:"publisher_confirms"`
  47. ConfirmTimeout int `yaml:"confirm_timeout"`
  48. }
  49. // HTTPConfig HTTP客户端配置
  50. type HTTPConfig struct {
  51. Timeout int `yaml:"timeout"`
  52. MaxIdleConns int `yaml:"max_idle_conns"`
  53. MaxIdleConnsPerHost int `yaml:"max_idle_conns_per_host"`
  54. IdleConnTimeout int `yaml:"idle_conn_timeout"`
  55. MaxConnsPerHost int `yaml:"max_conns_per_host"`
  56. DisableCompression bool `yaml:"disable_compression"`
  57. DisableKeepAlives bool `yaml:"disable_keep_alives"`
  58. }
  59. // DBConfig 数据库配置
  60. type DBConfig struct {
  61. Type string `yaml:"type"`
  62. Host string `yaml:"host"`
  63. Port int `yaml:"port"`
  64. Username string `yaml:"username"`
  65. Password string `yaml:"password"`
  66. Database string `yaml:"database"`
  67. MaxOpenConns int `yaml:"max_open_conns"`
  68. MaxIdleConns int `yaml:"max_idle_conns"`
  69. ConnMaxLifetime int `yaml:"conn_max_lifetime"`
  70. }
  71. // RedisConfig Redis配置
  72. type RedisConfig struct {
  73. Host string `yaml:"host"`
  74. Port int `yaml:"port"`
  75. Password string `yaml:"password"`
  76. DB int `yaml:"db"`
  77. PoolSize int `yaml:"pool_size"`
  78. DialTimeout int `yaml:"dial_timeout"`
  79. ReadTimeout int `yaml:"read_timeout"`
  80. WriteTimeout int `yaml:"write_timeout"`
  81. IdleTimeout int `yaml:"idle_timeout"`
  82. MaxConnAge int `yaml:"max_conn_age"`
  83. }
  84. // DorisConfig Doris配置
  85. type DorisConfig struct {
  86. FEHost string `yaml:"fe_host"`
  87. FEPort int `yaml:"fe_port"`
  88. FEUsername string `yaml:"fe_username"`
  89. FEPassword string `yaml:"fe_password"`
  90. MySQLHost string `yaml:"mysql_host"`
  91. MySQLPort int `yaml:"mysql_port"`
  92. MaxOpenConns int `yaml:"max_open_conns"`
  93. MaxIdleConns int `yaml:"max_idle_conns"`
  94. ConnMaxLifetime int `yaml:"conn_max_lifetime"`
  95. StreamLoadTimeout int `yaml:"stream_load_timeout"`
  96. BatchSize int `yaml:"batch_size"`
  97. }
  98. // Auth 认证配置
  99. type Auth struct {
  100. Token string `yaml:"token"`
  101. }
  102. // Service 微服务配置
  103. type Service struct {
  104. ServiceName string `yaml:"service_name"`
  105. ServiceVersion string `yaml:"service_version"`
  106. ServiceTag string `yaml:"service_tags"`
  107. Port int `yaml:"port"`
  108. ReadTimeout int `yaml:"read_timeout"`
  109. WriteTimeout int `yaml:"write_timeout"`
  110. IdleTimeout int `yaml:"idle_timeout"`
  111. TrustedProxies string `yaml:"trusted_proxies"`
  112. }
  113. // MicroConfig Go Micro微服务配置
  114. type MicroConfig struct {
  115. RegistryAddress string `yaml:"registry_address"`
  116. RegistryType string `yaml:"registry_type"`
  117. RegistryTimeout int `yaml:"registry_timeout"`
  118. LBStrategy string `yaml:"lb_strategy"`
  119. LBCacheTTL int `yaml:"lb_cache_ttl"`
  120. LBRetries int `yaml:"lb_retries"`
  121. ClientTimeout int `yaml:"client_timeout"`
  122. ClientPoolSize int `yaml:"client_pool_size"`
  123. MaxRetries int `yaml:"max_retries"`
  124. CircuitEnabled bool `yaml:"circuit_enabled"`
  125. CircuitTimeout int `yaml:"circuit_timeout"`
  126. ErrorThreshold int `yaml:"error_threshold"`
  127. SleepWindow int `yaml:"sleep_window"`
  128. HealthPath string `yaml:"health_path"`
  129. HealthInterval int `yaml:"health_interval"`
  130. HealthTimeout int `yaml:"health_timeout"`
  131. LogLevel string `yaml:"log_level"`
  132. EnableDebug bool `yaml:"enable_debug"`
  133. MetricsEnabled bool `yaml:"metrics_enabled"`
  134. MetricsAddress string `yaml:"metrics_address"`
  135. TracerEnabled bool `yaml:"tracer_enabled"`
  136. TracerAddress string `yaml:"tracer_address"`
  137. }
  138. // ==================== 配置接口定义 ====================
  139. // IConfig 配置接口
  140. type IConfig interface {
  141. GetDatabase() DBConfig
  142. GetRedis() RedisConfig
  143. GetDoris() DorisConfig
  144. GetRabbitMQ() RabbitMQConfig
  145. GetAuth() Auth
  146. GetService() Service
  147. GetHTTP() HTTPConfig
  148. GetMicro() MicroConfig
  149. IsDatabaseConfigured() bool
  150. IsRedisConfigured() bool
  151. IsDorisConfigured() bool
  152. IsRabbitMQConfigured() bool
  153. IsHTTPConfigured() bool
  154. IsAuthConfigured() bool
  155. IsMicroConfigured() bool
  156. }
  157. // configWrapper 配置包装器
  158. type configWrapper struct {
  159. config *Config
  160. }
  161. // ==================== 接口实现 ====================
  162. func (cw *configWrapper) GetDatabase() DBConfig {
  163. return cw.config.Database
  164. }
  165. func (cw *configWrapper) GetRedis() RedisConfig {
  166. return cw.config.Redis
  167. }
  168. func (cw *configWrapper) GetDoris() DorisConfig {
  169. return cw.config.Doris
  170. }
  171. func (cw *configWrapper) GetRabbitMQ() RabbitMQConfig {
  172. return cw.config.RabbitMQ
  173. }
  174. func (cw *configWrapper) GetAuth() Auth {
  175. return cw.config.Auth
  176. }
  177. func (cw *configWrapper) GetService() Service {
  178. return cw.config.Service
  179. }
  180. func (cw *configWrapper) GetHTTP() HTTPConfig {
  181. return cw.config.HTTP
  182. }
  183. func (cw *configWrapper) GetMicro() MicroConfig {
  184. return cw.config.Micro
  185. }
  186. func (cw *configWrapper) IsDatabaseConfigured() bool {
  187. db := cw.config.Database
  188. return db.Type != "" &&
  189. db.Host != "" &&
  190. db.Port > 0 &&
  191. db.Username != "" &&
  192. db.Database != ""
  193. }
  194. func (cw *configWrapper) IsRedisConfigured() bool {
  195. redis := cw.config.Redis
  196. return redis.Host != "" && redis.Port > 0
  197. }
  198. func (cw *configWrapper) IsDorisConfigured() bool {
  199. doris := cw.config.Doris
  200. return doris.FEHost != "" && doris.FEPort > 0
  201. }
  202. func (cw *configWrapper) IsRabbitMQConfigured() bool {
  203. rabbit := cw.config.RabbitMQ
  204. return rabbit.Host != "" && rabbit.Port > 0
  205. }
  206. func (cw *configWrapper) IsHTTPConfigured() bool {
  207. httpCfg := cw.config.HTTP
  208. return httpCfg.Timeout > 0
  209. }
  210. func (cw *configWrapper) IsAuthConfigured() bool {
  211. return cw.config.Auth.Token != ""
  212. }
  213. func (cw *configWrapper) IsMicroConfigured() bool {
  214. micro := cw.config.Micro
  215. return micro.RegistryAddress != ""
  216. }
  217. // ==================== 单例和全局变量 ====================
  218. var (
  219. instance IConfig
  220. once sync.Once
  221. initErr error
  222. )
  223. // GetConfig 获取配置单例实例
  224. func GetConfig() IConfig {
  225. once.Do(func() {
  226. config, err := loadConfig()
  227. if err != nil {
  228. initErr = err
  229. instance = &configWrapper{config: &Config{}}
  230. return
  231. }
  232. instance = &configWrapper{config: config}
  233. })
  234. return instance
  235. }
  236. // GetInitError 获取初始化错误(如果有)
  237. func GetInitError() error {
  238. return initErr
  239. }
  240. // ==================== 配置文件加载 ====================
  241. // loadConfig 加载配置文件(整合所有默认值)
  242. func loadConfig() (*Config, error) {
  243. configFile, err := findConfigFile()
  244. if err != nil {
  245. return nil, err
  246. }
  247. fmt.Printf("✅ Using config file: %s\n", configFile)
  248. // 创建带默认值的配置
  249. config := &Config{
  250. Service: Service{
  251. ServiceName: "myService",
  252. Port: 8080,
  253. ReadTimeout: 30,
  254. WriteTimeout: 30,
  255. IdleTimeout: 60,
  256. TrustedProxies: "",
  257. },
  258. Redis: RedisConfig{
  259. Port: 6379,
  260. DB: 0,
  261. PoolSize: 10,
  262. DialTimeout: 5,
  263. ReadTimeout: 3,
  264. WriteTimeout: 3,
  265. IdleTimeout: 300,
  266. MaxConnAge: 0,
  267. },
  268. Doris: DorisConfig{
  269. FEPort: 8030,
  270. MySQLPort: 9030,
  271. MaxOpenConns: 20,
  272. MaxIdleConns: 10,
  273. ConnMaxLifetime: 3600,
  274. StreamLoadTimeout: 30,
  275. BatchSize: 1000,
  276. },
  277. HTTP: HTTPConfig{
  278. Timeout: 30,
  279. MaxIdleConns: 100,
  280. MaxIdleConnsPerHost: 10,
  281. IdleConnTimeout: 90,
  282. MaxConnsPerHost: 0,
  283. DisableCompression: false,
  284. DisableKeepAlives: false,
  285. },
  286. RabbitMQ: RabbitMQConfig{
  287. Port: 5672,
  288. Username: "guest",
  289. Password: "guest",
  290. Vhost: "/",
  291. UseTLS: false,
  292. MaxOpenChannels: 10,
  293. ReconnectDelay: 5000,
  294. MaxReconnectAttempts: 10,
  295. Heartbeat: 30,
  296. ChannelSize: 100,
  297. DefaultExchange: "amq.direct",
  298. DefaultQueue: "",
  299. AutoAck: false,
  300. Mandatory: false,
  301. Immediate: false,
  302. PrefetchCount: 1,
  303. PrefetchSize: 0,
  304. Global: false,
  305. PublisherConfirms: false,
  306. ConfirmTimeout: 30,
  307. },
  308. Micro: MicroConfig{
  309. RegistryAddress: "localhost:8500",
  310. RegistryType: "consul",
  311. RegistryTimeout: 10,
  312. LBStrategy: "roundrobin",
  313. LBCacheTTL: 30,
  314. LBRetries: 3,
  315. ClientTimeout: 30,
  316. ClientPoolSize: 100,
  317. MaxRetries: 3,
  318. CircuitEnabled: true,
  319. CircuitTimeout: 60,
  320. ErrorThreshold: 5,
  321. SleepWindow: 5000,
  322. HealthPath: "/health",
  323. HealthInterval: 10,
  324. HealthTimeout: 5,
  325. LogLevel: "info",
  326. EnableDebug: false,
  327. MetricsEnabled: true,
  328. MetricsAddress: ":9090",
  329. TracerEnabled: false,
  330. TracerAddress: "localhost:6831",
  331. },
  332. }
  333. // 读取并解析配置文件
  334. data, err := os.ReadFile(configFile)
  335. if err != nil {
  336. return nil, fmt.Errorf("failed to read config file %s: %v", configFile, err)
  337. }
  338. err = yaml.Unmarshal(data, &config)
  339. if err != nil {
  340. return nil, fmt.Errorf("failed to parse config file: %v", err)
  341. }
  342. return config, nil
  343. }
  344. // findConfigFile 查找配置文件路径
  345. func findConfigFile() (string, error) {
  346. // 1. 可执行文件同目录
  347. exePath, err := os.Executable()
  348. if err == nil {
  349. exeDir := filepath.Dir(exePath)
  350. configFile := filepath.Join(exeDir, "db.yaml")
  351. if _, err := os.Stat(configFile); err == nil {
  352. return configFile, nil
  353. }
  354. }
  355. // 2. 环境变量指定路径
  356. envConfigPath := os.Getenv("DB_CONFIG_PATH")
  357. if envConfigPath != "" {
  358. if _, err := os.Stat(envConfigPath); err == nil {
  359. return envConfigPath, nil
  360. }
  361. return "", fmt.Errorf("DB_CONFIG_PATH file not found: %s", envConfigPath)
  362. }
  363. // 3. 未找到配置文件
  364. exeDir := "unknown"
  365. if exePath, err := os.Executable(); err == nil {
  366. exeDir = filepath.Dir(exePath)
  367. }
  368. return "", fmt.Errorf(`no configuration file found!
  369. Tried locations:
  370. 1. Executable directory: %s/db.yaml
  371. 2. Environment variable: DB_CONFIG_PATH
  372. Solutions:
  373. - Place db.yaml in the same directory as the executable
  374. - Or set DB_CONFIG_PATH environment variable to config file path
  375. Example:
  376. export DB_CONFIG_PATH=/path/to/your/db.yaml`, exeDir)
  377. }