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  }