dubbo.apache.org/dubbo-go/v3@v3.1.1/config/root_config.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package config 19 20 import ( 21 "sync" 22 ) 23 24 import ( 25 hessian "github.com/apache/dubbo-go-hessian2" 26 27 "github.com/dubbogo/gost/log/logger" 28 29 "github.com/knadh/koanf" 30 31 perrors "github.com/pkg/errors" 32 33 "go.uber.org/atomic" 34 ) 35 36 import ( 37 "dubbo.apache.org/dubbo-go/v3/common" 38 "dubbo.apache.org/dubbo-go/v3/common/constant" 39 "dubbo.apache.org/dubbo-go/v3/common/extension" 40 "dubbo.apache.org/dubbo-go/v3/config_center" 41 "dubbo.apache.org/dubbo-go/v3/metadata/service/exporter" 42 ) 43 44 var ( 45 startOnce sync.Once 46 exporting = &atomic.Bool{} 47 ) 48 49 // RootConfig is the root config 50 type RootConfig struct { 51 Application *ApplicationConfig `validate:"required" yaml:"application" json:"application,omitempty" property:"application"` 52 Protocols map[string]*ProtocolConfig `validate:"required" yaml:"protocols" json:"protocols" property:"protocols"` 53 Registries map[string]*RegistryConfig `yaml:"registries" json:"registries" property:"registries"` 54 ConfigCenter *CenterConfig `yaml:"config-center" json:"config-center,omitempty"` 55 MetadataReport *MetadataReportConfig `yaml:"metadata-report" json:"metadata-report,omitempty" property:"metadata-report"` 56 Provider *ProviderConfig `yaml:"provider" json:"provider" property:"provider"` 57 Consumer *ConsumerConfig `yaml:"consumer" json:"consumer" property:"consumer"` 58 Otel *OtelConfig `yaml:"otel" json:"otel,omitempty" property:"otel"` 59 Metric *MetricConfig `yaml:"metrics" json:"metrics,omitempty" property:"metrics"` 60 Tracing map[string]*TracingConfig `yaml:"tracing" json:"tracing,omitempty" property:"tracing"` 61 Logger *LoggerConfig `yaml:"logger" json:"logger,omitempty" property:"logger"` 62 Shutdown *ShutdownConfig `yaml:"shutdown" json:"shutdown,omitempty" property:"shutdown"` 63 Router []*RouterConfig `yaml:"router" json:"router,omitempty" property:"router"` 64 EventDispatcherType string `default:"direct" yaml:"event-dispatcher-type" json:"event-dispatcher-type,omitempty"` 65 CacheFile string `yaml:"cache_file" json:"cache_file,omitempty" property:"cache_file"` 66 Custom *CustomConfig `yaml:"custom" json:"custom,omitempty" property:"custom"` 67 Profiles *ProfilesConfig `yaml:"profiles" json:"profiles,omitempty" property:"profiles"` 68 TLSConfig *TLSConfig `yaml:"tls_config" json:"tls_config,omitempty" property:"tls_config"` 69 } 70 71 func SetRootConfig(r RootConfig) { 72 rootConfig = &r 73 } 74 75 // Prefix dubbo 76 func (rc *RootConfig) Prefix() string { 77 return constant.Dubbo 78 } 79 80 func GetRootConfig() *RootConfig { 81 return rootConfig 82 } 83 84 func GetProviderConfig() *ProviderConfig { 85 if err := check(); err == nil && rootConfig.Provider != nil { 86 return rootConfig.Provider 87 } 88 return NewProviderConfigBuilder().Build() 89 } 90 91 func GetConsumerConfig() *ConsumerConfig { 92 if err := check(); err == nil && rootConfig.Consumer != nil { 93 return rootConfig.Consumer 94 } 95 return NewConsumerConfigBuilder().Build() 96 } 97 98 func GetApplicationConfig() *ApplicationConfig { 99 return rootConfig.Application 100 } 101 102 func GetShutDown() *ShutdownConfig { 103 if err := check(); err == nil && rootConfig.Shutdown != nil { 104 return rootConfig.Shutdown 105 } 106 return NewShutDownConfigBuilder().Build() 107 } 108 109 func GetTLSConfig() *TLSConfig { 110 if err := check(); err == nil && rootConfig.TLSConfig != nil { 111 return rootConfig.TLSConfig 112 } 113 return NewTLSConfigBuilder().Build() 114 } 115 116 // getRegistryIds get registry ids 117 func (rc *RootConfig) getRegistryIds() []string { 118 ids := make([]string, 0) 119 for key := range rc.Registries { 120 ids = append(ids, key) 121 } 122 return removeDuplicateElement(ids) 123 } 124 func registerPOJO() { 125 hessian.RegisterPOJO(&common.MetadataInfo{}) 126 hessian.RegisterPOJO(&common.ServiceInfo{}) 127 hessian.RegisterPOJO(&common.URL{}) 128 } 129 130 // Init is to start dubbo-go framework, load local configuration, or read configuration from config-center if necessary. 131 // It's deprecated for user to call rootConfig.Init() manually, try config.Load(config.WithRootConfig(rootConfig)) instead. 132 func (rc *RootConfig) Init() error { 133 registerPOJO() 134 if err := rc.Logger.Init(); err != nil { // init default logger 135 return err 136 } 137 if err := rc.ConfigCenter.Init(rc); err != nil { 138 logger.Infof("[Config Center] Config center doesn't start") 139 logger.Debugf("config center doesn't start because %s", err) 140 } else { 141 if err = rc.Logger.Init(); err != nil { // init logger using config from config center again 142 return err 143 } 144 } 145 146 if err := rc.Application.Init(); err != nil { 147 return err 148 } 149 150 // init user define 151 if err := rc.Custom.Init(); err != nil { 152 return err 153 } 154 155 // init protocol 156 protocols := rc.Protocols 157 if len(protocols) <= 0 { 158 protocol := &ProtocolConfig{} 159 protocols = make(map[string]*ProtocolConfig, 1) 160 protocols[constant.Dubbo] = protocol 161 rc.Protocols = protocols 162 } 163 for _, protocol := range protocols { 164 if err := protocol.Init(); err != nil { 165 return err 166 } 167 } 168 169 // init registry 170 for _, reg := range rc.Registries { 171 if err := reg.Init(); err != nil { 172 return err 173 } 174 } 175 176 if err := rc.MetadataReport.Init(rc); err != nil { 177 return err 178 } 179 if err := rc.Otel.Init(rc.Application); err != nil { 180 return err 181 } 182 if err := rc.Metric.Init(rc); err != nil { 183 return err 184 } 185 for _, t := range rc.Tracing { 186 if err := t.Init(); err != nil { 187 return err 188 } 189 } 190 if err := initRouterConfig(rc); err != nil { 191 return err 192 } 193 // provider、consumer must last init 194 if err := rc.Provider.Init(rc); err != nil { 195 return err 196 } 197 if err := rc.Consumer.Init(rc); err != nil { 198 return err 199 } 200 if err := rc.Shutdown.Init(); err != nil { 201 return err 202 } 203 SetRootConfig(*rc) 204 // todo if we can remove this from Init in the future? 205 rc.Start() 206 return nil 207 } 208 209 func (rc *RootConfig) Start() { 210 startOnce.Do(func() { 211 gracefulShutdownInit() 212 rc.Consumer.Load() 213 rc.Provider.Load() 214 // todo if register consumer instance or has exported services 215 exportMetadataService() 216 registerServiceInstance() 217 }) 218 } 219 220 // newEmptyRootConfig get empty root config 221 func newEmptyRootConfig() *RootConfig { 222 newRootConfig := &RootConfig{ 223 ConfigCenter: NewConfigCenterConfigBuilder().Build(), 224 MetadataReport: NewMetadataReportConfigBuilder().Build(), 225 Application: NewApplicationConfigBuilder().Build(), 226 Registries: make(map[string]*RegistryConfig), 227 Protocols: make(map[string]*ProtocolConfig), 228 Tracing: make(map[string]*TracingConfig), 229 Provider: NewProviderConfigBuilder().Build(), 230 Consumer: NewConsumerConfigBuilder().Build(), 231 Otel: NewOtelConfigBuilder().Build(), 232 Metric: NewMetricConfigBuilder().Build(), 233 Logger: NewLoggerConfigBuilder().Build(), 234 Custom: NewCustomConfigBuilder().Build(), 235 Shutdown: NewShutDownConfigBuilder().Build(), 236 TLSConfig: NewTLSConfigBuilder().Build(), 237 } 238 return newRootConfig 239 } 240 241 func NewRootConfigBuilder() *RootConfigBuilder { 242 return &RootConfigBuilder{rootConfig: newEmptyRootConfig()} 243 } 244 245 type RootConfigBuilder struct { 246 rootConfig *RootConfig 247 } 248 249 func (rb *RootConfigBuilder) SetApplication(application *ApplicationConfig) *RootConfigBuilder { 250 rb.rootConfig.Application = application 251 return rb 252 } 253 254 func (rb *RootConfigBuilder) AddProtocol(protocolID string, protocolConfig *ProtocolConfig) *RootConfigBuilder { 255 rb.rootConfig.Protocols[protocolID] = protocolConfig 256 return rb 257 } 258 259 func (rb *RootConfigBuilder) AddRegistry(registryID string, registryConfig *RegistryConfig) *RootConfigBuilder { 260 rb.rootConfig.Registries[registryID] = registryConfig 261 return rb 262 } 263 264 func (rb *RootConfigBuilder) SetProtocols(protocols map[string]*ProtocolConfig) *RootConfigBuilder { 265 rb.rootConfig.Protocols = protocols 266 return rb 267 } 268 269 func (rb *RootConfigBuilder) SetRegistries(registries map[string]*RegistryConfig) *RootConfigBuilder { 270 rb.rootConfig.Registries = registries 271 return rb 272 } 273 274 func (rb *RootConfigBuilder) SetMetadataReport(metadataReport *MetadataReportConfig) *RootConfigBuilder { 275 rb.rootConfig.MetadataReport = metadataReport 276 return rb 277 } 278 279 func (rb *RootConfigBuilder) SetProvider(provider *ProviderConfig) *RootConfigBuilder { 280 rb.rootConfig.Provider = provider 281 return rb 282 } 283 284 func (rb *RootConfigBuilder) SetConsumer(consumer *ConsumerConfig) *RootConfigBuilder { 285 rb.rootConfig.Consumer = consumer 286 return rb 287 } 288 289 func (rb *RootConfigBuilder) SetOtel(otel *OtelConfig) *RootConfigBuilder { 290 rb.rootConfig.Otel = otel 291 return rb 292 } 293 294 func (rb *RootConfigBuilder) SetMetric(metric *MetricConfig) *RootConfigBuilder { 295 rb.rootConfig.Metric = metric 296 return rb 297 } 298 299 func (rb *RootConfigBuilder) SetLogger(logger *LoggerConfig) *RootConfigBuilder { 300 rb.rootConfig.Logger = logger 301 return rb 302 } 303 304 func (rb *RootConfigBuilder) SetShutdown(shutdown *ShutdownConfig) *RootConfigBuilder { 305 rb.rootConfig.Shutdown = shutdown 306 return rb 307 } 308 309 func (rb *RootConfigBuilder) SetRouter(router []*RouterConfig) *RootConfigBuilder { 310 rb.rootConfig.Router = router 311 return rb 312 } 313 314 func (rb *RootConfigBuilder) SetEventDispatcherType(eventDispatcherType string) *RootConfigBuilder { 315 rb.rootConfig.EventDispatcherType = eventDispatcherType 316 return rb 317 } 318 319 func (rb *RootConfigBuilder) SetCacheFile(cacheFile string) *RootConfigBuilder { 320 rb.rootConfig.CacheFile = cacheFile 321 return rb 322 } 323 324 func (rb *RootConfigBuilder) SetConfigCenter(configCenterConfig *CenterConfig) *RootConfigBuilder { 325 rb.rootConfig.ConfigCenter = configCenterConfig 326 return rb 327 } 328 329 func (rb *RootConfigBuilder) SetCustom(customConfig *CustomConfig) *RootConfigBuilder { 330 rb.rootConfig.Custom = customConfig 331 return rb 332 } 333 334 func (rb *RootConfigBuilder) SetShutDown(shutDownConfig *ShutdownConfig) *RootConfigBuilder { 335 rb.rootConfig.Shutdown = shutDownConfig 336 return rb 337 } 338 339 func (rb *RootConfigBuilder) SetTLSConfig(tlsConfig *TLSConfig) *RootConfigBuilder { 340 rb.rootConfig.TLSConfig = tlsConfig 341 return rb 342 } 343 344 func (rb *RootConfigBuilder) Build() *RootConfig { 345 return rb.rootConfig 346 } 347 348 func exportMetadataService() { 349 ms, err := extension.GetLocalMetadataService(constant.DefaultKey) 350 if err != nil { 351 logger.Warnf("could not init metadata service", err) 352 return 353 } 354 355 if !IsProvider() || exporting.Load() { 356 return 357 } 358 359 // In theory, we can use sync.Once 360 // But sync.Once is not reentrant. 361 // Now the invocation chain is createRegistry -> tryInitMetadataService -> metadataServiceExporter.export 362 // -> createRegistry -> initMetadataService... 363 // So using sync.Once will result in dead lock 364 exporting.Store(true) 365 366 expt := extension.GetMetadataServiceExporter(constant.DefaultKey, ms) 367 if expt == nil { 368 logger.Warnf("get metadata service exporter failed, pls check if you import _ \"dubbo.apache.org/dubbo-go/v3/metadata/service/exporter/configurable\"") 369 return 370 } 371 372 err = expt.Export(nil) 373 if err != nil { 374 logger.Errorf("could not export the metadata service, err = %s", err.Error()) 375 return 376 } 377 378 // report interface-app mapping 379 err = publishMapping(expt) 380 if err != nil { 381 logger.Errorf("Publish interface-application mapping failed, got error %#v", err) 382 } 383 } 384 385 // OnEvent only handle ServiceConfigExportedEvent 386 func publishMapping(sc exporter.MetadataServiceExporter) error { 387 urls := sc.GetExportedURLs() 388 389 for _, u := range urls { 390 err := extension.GetGlobalServiceNameMapping().Map(u) 391 if err != nil { 392 return perrors.WithMessage(err, "could not map the service: "+u.String()) 393 } 394 } 395 return nil 396 } 397 398 // Process receive changing listener's event, dynamic update config 399 func (rc *RootConfig) Process(event *config_center.ConfigChangeEvent) { 400 logger.Infof("CenterConfig process event:\n%+v", event) 401 config := NewLoaderConf(WithBytes([]byte(event.Value.(string)))) 402 koan := GetConfigResolver(config) 403 404 updateRootConfig := &RootConfig{} 405 if err := koan.UnmarshalWithConf(rc.Prefix(), 406 updateRootConfig, koanf.UnmarshalConf{Tag: "yaml"}); err != nil { 407 logger.Errorf("CenterConfig process unmarshalConf failed, got error %#v", err) 408 return 409 } 410 // dynamically update register 411 for registerId, updateRegister := range updateRootConfig.Registries { 412 register := rc.Registries[registerId] 413 register.DynamicUpdateProperties(updateRegister) 414 } 415 // dynamically update consumer 416 rc.Consumer.DynamicUpdateProperties(updateRootConfig.Consumer) 417 418 // dynamically update logger 419 rc.Logger.DynamicUpdateProperties(updateRootConfig.Logger) 420 421 // dynamically update metric 422 rc.Metric.DynamicUpdateProperties(updateRootConfig.Metric) 423 }