Нема описа
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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. package config
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "sync"
  7. "gopkg.in/yaml.v2"
  8. )
  9. // Config 应用配置
  10. type Config struct {
  11. Database DBConfig `yaml:"database"`
  12. Redis RedisConfig `yaml:"redis"`
  13. Doris DorisConfig `yaml:"doris"`
  14. RabbitMQ RabbitMQConfig `yaml:"rabbitmq"` // 新增 RabbitMQ 配置
  15. Auth Auth `yaml:"auth"`
  16. Service Service `yaml:"service"`
  17. HTTP HTTPConfig `yaml:"http"`
  18. }
  19. // RabbitMQConfig RabbitMQ配置
  20. type RabbitMQConfig struct {
  21. // 连接配置
  22. Host string `yaml:"host"`
  23. Port int `yaml:"port"`
  24. Username string `yaml:"username"`
  25. Password string `yaml:"password"`
  26. Vhost string `yaml:"vhost"`
  27. // TLS配置
  28. UseTLS bool `yaml:"use_tls"`
  29. CACert string `yaml:"ca_cert"`
  30. CertFile string `yaml:"cert_file"`
  31. KeyFile string `yaml:"key_file"`
  32. // 连接池和超时配置
  33. MaxOpenChannels int `yaml:"max_open_channels"` // 最大通道数
  34. ReconnectDelay int `yaml:"reconnect_delay"` // 重连延迟(毫秒)
  35. MaxReconnectAttempts int `yaml:"max_reconnect_attempts"` // 最大重试次数
  36. // 心跳和超时
  37. Heartbeat int `yaml:"heartbeat"` // 心跳间隔(秒)
  38. ChannelSize int `yaml:"channel_size"` // 通道缓冲区大小
  39. // 队列和交换机默认配置
  40. DefaultExchange string `yaml:"default_exchange"`
  41. DefaultQueue string `yaml:"default_queue"`
  42. // 消息确认模式
  43. AutoAck bool `yaml:"auto_ack"`
  44. Mandatory bool `yaml:"mandatory"`
  45. Immediate bool `yaml:"immediate"`
  46. // QoS配置
  47. PrefetchCount int `yaml:"prefetch_count"` // 预取数量
  48. PrefetchSize int `yaml:"prefetch_size"` // 预取大小(字节)
  49. Global bool `yaml:"global"` // 是否是全局QoS
  50. // 发布确认
  51. PublisherConfirms bool `yaml:"publisher_confirms"` // 是否启用发布者确认
  52. ConfirmTimeout int `yaml:"confirm_timeout"` // 确认超时(秒)
  53. }
  54. // HTTPConfig HTTP客户端配置
  55. type HTTPConfig struct {
  56. Timeout int `yaml:"timeout"`
  57. MaxIdleConns int `yaml:"max_idle_conns"`
  58. MaxIdleConnsPerHost int `yaml:"max_idle_conns_per_host"`
  59. IdleConnTimeout int `yaml:"idle_conn_timeout"`
  60. MaxConnsPerHost int `yaml:"max_conns_per_host"`
  61. DisableCompression bool `yaml:"disable_compression"`
  62. DisableKeepAlives bool `yaml:"disable_keep_alives"`
  63. }
  64. // DBConfig 数据库配置
  65. type DBConfig struct {
  66. Type string `yaml:"type"`
  67. Host string `yaml:"host"`
  68. Port int `yaml:"port"`
  69. Username string `yaml:"username"`
  70. Password string `yaml:"password"`
  71. Database string `yaml:"database"`
  72. MaxOpenConns int `yaml:"max_open_conns"`
  73. MaxIdleConns int `yaml:"max_idle_conns"`
  74. ConnMaxLifetime int `yaml:"conn_max_lifetime"`
  75. }
  76. // RedisConfig Redis配置
  77. type RedisConfig struct {
  78. Host string `yaml:"host"`
  79. Port int `yaml:"port"`
  80. Password string `yaml:"password"`
  81. DB int `yaml:"db"`
  82. PoolSize int `yaml:"pool_size"`
  83. DialTimeout int `yaml:"dial_timeout"`
  84. ReadTimeout int `yaml:"read_timeout"`
  85. WriteTimeout int `yaml:"write_timeout"`
  86. IdleTimeout int `yaml:"idle_timeout"`
  87. MaxConnAge int `yaml:"max_conn_age"`
  88. }
  89. // DorisConfig Doris配置
  90. type DorisConfig struct {
  91. FEHost string `yaml:"fe_host"`
  92. FEPort int `yaml:"fe_port"`
  93. FEUsername string `yaml:"fe_username"`
  94. FEPassword string `yaml:"fe_password"`
  95. MySQLHost string `yaml:"mysql_host"`
  96. MySQLPort int `yaml:"mysql_port"`
  97. MaxOpenConns int `yaml:"max_open_conns"`
  98. MaxIdleConns int `yaml:"max_idle_conns"`
  99. ConnMaxLifetime int `yaml:"conn_max_lifetime"`
  100. StreamLoadTimeout int `yaml:"stream_load_timeout"`
  101. BatchSize int `yaml:"batch_size"`
  102. }
  103. // Auth 认证配置
  104. type Auth struct {
  105. Token string `yaml:"token"`
  106. }
  107. // Service 微服务配置
  108. type Service struct {
  109. ServiceName string `yaml:"service_name"`
  110. Port int `yaml:"port"`
  111. ReadTimeout int `yaml:"read_timeout"`
  112. WriteTimeout int `yaml:"write_timeout"`
  113. IdleTimeout int `yaml:"idle_timeout"`
  114. TrustedProxies string `yaml:"trusted_proxies"`
  115. }
  116. // 导出接口,防止外部修改
  117. type IConfig interface {
  118. GetDatabase() DBConfig
  119. GetRedis() RedisConfig
  120. GetDoris() DorisConfig
  121. GetRabbitMQ() RabbitMQConfig // 新增获取RabbitMQ配置方法
  122. GetAuth() Auth
  123. GetService() Service
  124. GetHTTP() HTTPConfig
  125. IsDatabaseConfigured() bool
  126. IsRedisConfigured() bool
  127. IsDorisConfigured() bool
  128. IsRabbitMQConfigured() bool // 新增检查RabbitMQ配置方法
  129. IsHTTPConfigured() bool
  130. IsAuthConfigured() bool
  131. }
  132. // 实现接口的具体类型
  133. type configWrapper struct {
  134. config *Config
  135. }
  136. func (cw *configWrapper) GetDatabase() DBConfig {
  137. return cw.config.Database
  138. }
  139. func (cw *configWrapper) GetRedis() RedisConfig {
  140. return cw.config.Redis
  141. }
  142. func (cw *configWrapper) GetDoris() DorisConfig {
  143. return cw.config.Doris
  144. }
  145. func (cw *configWrapper) GetRabbitMQ() RabbitMQConfig {
  146. return cw.config.RabbitMQ
  147. }
  148. func (cw *configWrapper) GetAuth() Auth {
  149. return cw.config.Auth
  150. }
  151. func (cw *configWrapper) GetService() Service {
  152. return cw.config.Service
  153. }
  154. func (cw *configWrapper) GetHTTP() HTTPConfig {
  155. return cw.config.HTTP
  156. }
  157. func (cw *configWrapper) IsDatabaseConfigured() bool {
  158. db := cw.config.Database
  159. return db.Type != "" &&
  160. db.Host != "" &&
  161. db.Port > 0 &&
  162. db.Username != "" &&
  163. db.Database != ""
  164. }
  165. func (cw *configWrapper) IsRedisConfigured() bool {
  166. redis := cw.config.Redis
  167. return redis.Host != "" && redis.Port > 0
  168. }
  169. func (cw *configWrapper) IsDorisConfigured() bool {
  170. doris := cw.config.Doris
  171. return doris.FEHost != "" && doris.FEPort > 0
  172. }
  173. func (cw *configWrapper) IsRabbitMQConfigured() bool {
  174. rabbit := cw.config.RabbitMQ
  175. // 基础连接配置检查
  176. return rabbit.Host != "" && rabbit.Port > 0
  177. }
  178. func (cw *configWrapper) IsHTTPConfigured() bool {
  179. httpCfg := cw.config.HTTP
  180. return httpCfg.Timeout > 0
  181. }
  182. func (cw *configWrapper) IsAuthConfigured() bool {
  183. return cw.config.Auth.Token != ""
  184. }
  185. var (
  186. instance IConfig
  187. once sync.Once
  188. initErr error
  189. )
  190. // GetConfig 获取配置单例实例
  191. func GetConfig() IConfig {
  192. once.Do(func() {
  193. config, err := loadConfig()
  194. if err != nil {
  195. initErr = err
  196. instance = &configWrapper{config: &Config{}}
  197. return
  198. }
  199. instance = &configWrapper{config: config}
  200. })
  201. return instance
  202. }
  203. // GetInitError 获取初始化错误(如果有)
  204. func GetInitError() error {
  205. return initErr
  206. }
  207. // loadConfig 加载配置文件
  208. func loadConfig() (*Config, error) {
  209. configFile, err := findConfigFile()
  210. if err != nil {
  211. return nil, err
  212. }
  213. fmt.Printf("✅ Using config file: %s\n", configFile)
  214. // 先创建带默认值的配置
  215. config := &Config{
  216. Service: Service{
  217. ServiceName: "myService",
  218. Port: 8080,
  219. ReadTimeout: 30,
  220. WriteTimeout: 30,
  221. IdleTimeout: 60,
  222. TrustedProxies: "",
  223. },
  224. Redis: RedisConfig{
  225. Port: 6379,
  226. DB: 0,
  227. PoolSize: 10,
  228. DialTimeout: 5,
  229. ReadTimeout: 3,
  230. WriteTimeout: 3,
  231. IdleTimeout: 300,
  232. MaxConnAge: 0,
  233. },
  234. Doris: DorisConfig{
  235. FEPort: 8030,
  236. MySQLPort: 9030,
  237. MaxOpenConns: 20,
  238. MaxIdleConns: 10,
  239. ConnMaxLifetime: 3600,
  240. StreamLoadTimeout: 30,
  241. BatchSize: 1000,
  242. },
  243. HTTP: HTTPConfig{
  244. Timeout: 30,
  245. MaxIdleConns: 100,
  246. MaxIdleConnsPerHost: 10,
  247. IdleConnTimeout: 90,
  248. MaxConnsPerHost: 0,
  249. DisableCompression: false,
  250. DisableKeepAlives: false,
  251. },
  252. RabbitMQ: RabbitMQConfig{
  253. Port: 5672,
  254. Username: "guest",
  255. Password: "guest",
  256. Vhost: "/",
  257. UseTLS: false,
  258. MaxOpenChannels: 10,
  259. ReconnectDelay: 5000, // 5秒
  260. MaxReconnectAttempts: 10, // 最多重试10次
  261. Heartbeat: 30, // 30秒心跳
  262. ChannelSize: 100,
  263. DefaultExchange: "amq.direct",
  264. DefaultQueue: "",
  265. AutoAck: false, // 默认手动确认
  266. Mandatory: false,
  267. Immediate: false,
  268. PrefetchCount: 1, // 一次预取1条消息
  269. PrefetchSize: 0,
  270. Global: false,
  271. PublisherConfirms: false, // 默认不启用发布确认
  272. ConfirmTimeout: 30, // 5秒确认超时
  273. },
  274. }
  275. // 读取配置文件
  276. data, err := os.ReadFile(configFile)
  277. if err != nil {
  278. return nil, fmt.Errorf("failed to read config file %s: %v", configFile, err)
  279. }
  280. err = yaml.Unmarshal(data, &config)
  281. if err != nil {
  282. return nil, fmt.Errorf("failed to parse config file: %v", err)
  283. }
  284. return config, nil
  285. }
  286. // findConfigFile 查找配置文件
  287. func findConfigFile() (string, error) {
  288. // 1. 首先尝试可执行文件同目录
  289. exePath, err := os.Executable()
  290. if err == nil {
  291. exeDir := filepath.Dir(exePath)
  292. configFile := filepath.Join(exeDir, "db.yaml")
  293. if _, err := os.Stat(configFile); err == nil {
  294. return configFile, nil
  295. }
  296. }
  297. // 2. 尝试环境变量指定的路径
  298. envConfigPath := os.Getenv("DB_CONFIG_PATH")
  299. if envConfigPath != "" {
  300. if _, err := os.Stat(envConfigPath); err == nil {
  301. return envConfigPath, nil
  302. }
  303. return "", fmt.Errorf("DB_CONFIG_PATH file not found: %s", envConfigPath)
  304. }
  305. // 3. 如果都没有找到,返回错误
  306. exeDir := "unknown"
  307. if exePath, err := os.Executable(); err == nil {
  308. exeDir = filepath.Dir(exePath)
  309. }
  310. return "", fmt.Errorf(`no configuration file found!
  311. Tried locations:
  312. 1. Executable directory: %s/db.yaml
  313. 2. Environment variable: DB_CONFIG_PATH
  314. Solutions:
  315. - Place db.yaml in the same directory as the executable
  316. - Or set DB_CONFIG_PATH environment variable to config file path
  317. Example:
  318. export DB_CONFIG_PATH=/path/to/your/db.yaml`, exeDir)
  319. }