dubbo.apache.org/dubbo-go/v3@v3.1.1/config/service_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  	"container/list"
    22  	"fmt"
    23  	"net/url"
    24  	"os"
    25  	"strconv"
    26  	"strings"
    27  	"sync"
    28  	"time"
    29  )
    30  
    31  import (
    32  	"github.com/creasty/defaults"
    33  
    34  	"github.com/dubbogo/gost/log/logger"
    35  	gxnet "github.com/dubbogo/gost/net"
    36  
    37  	perrors "github.com/pkg/errors"
    38  
    39  	"go.uber.org/atomic"
    40  )
    41  
    42  import (
    43  	"dubbo.apache.org/dubbo-go/v3/common"
    44  	"dubbo.apache.org/dubbo-go/v3/common/constant"
    45  	"dubbo.apache.org/dubbo-go/v3/common/extension"
    46  	"dubbo.apache.org/dubbo-go/v3/protocol"
    47  	"dubbo.apache.org/dubbo-go/v3/protocol/protocolwrapper"
    48  )
    49  
    50  // ServiceConfig is the configuration of the service provider
    51  type ServiceConfig struct {
    52  	id                          string
    53  	Filter                      string            `yaml:"filter" json:"filter,omitempty" property:"filter"`
    54  	ProtocolIDs                 []string          `yaml:"protocol-ids"  json:"protocol-ids,omitempty" property:"protocol-ids"` // multi protocolIDs support, split by ','
    55  	Interface                   string            `yaml:"interface"  json:"interface,omitempty" property:"interface"`
    56  	RegistryIDs                 []string          `yaml:"registry-ids"  json:"registry-ids,omitempty"  property:"registry-ids"`
    57  	Cluster                     string            `default:"failover" yaml:"cluster"  json:"cluster,omitempty" property:"cluster"`
    58  	Loadbalance                 string            `default:"random" yaml:"loadbalance"  json:"loadbalance,omitempty"  property:"loadbalance"`
    59  	Group                       string            `yaml:"group"  json:"group,omitempty" property:"group"`
    60  	Version                     string            `yaml:"version"  json:"version,omitempty" property:"version" `
    61  	Methods                     []*MethodConfig   `yaml:"methods"  json:"methods,omitempty" property:"methods"`
    62  	Warmup                      string            `yaml:"warmup"  json:"warmup,omitempty"  property:"warmup"`
    63  	Retries                     string            `yaml:"retries"  json:"retries,omitempty" property:"retries"`
    64  	Serialization               string            `yaml:"serialization" json:"serialization" property:"serialization"`
    65  	Params                      map[string]string `yaml:"params"  json:"params,omitempty" property:"params"`
    66  	Token                       string            `yaml:"token" json:"token,omitempty" property:"token"`
    67  	AccessLog                   string            `yaml:"accesslog" json:"accesslog,omitempty" property:"accesslog"`
    68  	TpsLimiter                  string            `yaml:"tps.limiter" json:"tps.limiter,omitempty" property:"tps.limiter"`
    69  	TpsLimitInterval            string            `yaml:"tps.limit.interval" json:"tps.limit.interval,omitempty" property:"tps.limit.interval"`
    70  	TpsLimitRate                string            `yaml:"tps.limit.rate" json:"tps.limit.rate,omitempty" property:"tps.limit.rate"`
    71  	TpsLimitStrategy            string            `yaml:"tps.limit.strategy" json:"tps.limit.strategy,omitempty" property:"tps.limit.strategy"`
    72  	TpsLimitRejectedHandler     string            `yaml:"tps.limit.rejected.handler" json:"tps.limit.rejected.handler,omitempty" property:"tps.limit.rejected.handler"`
    73  	ExecuteLimit                string            `yaml:"execute.limit" json:"execute.limit,omitempty" property:"execute.limit"`
    74  	ExecuteLimitRejectedHandler string            `yaml:"execute.limit.rejected.handler" json:"execute.limit.rejected.handler,omitempty" property:"execute.limit.rejected.handler"`
    75  	Auth                        string            `yaml:"auth" json:"auth,omitempty" property:"auth"`
    76  	NotRegister                 bool              `yaml:"not_register" json:"not_register,omitempty" property:"not_register"`
    77  	ParamSign                   string            `yaml:"param.sign" json:"param.sign,omitempty" property:"param.sign"`
    78  	Tag                         string            `yaml:"tag" json:"tag,omitempty" property:"tag"`
    79  	TracingKey                  string            `yaml:"tracing-key" json:"tracing-key,omitempty" propertiy:"tracing-key"`
    80  
    81  	RCProtocolsMap  map[string]*ProtocolConfig
    82  	RCRegistriesMap map[string]*RegistryConfig
    83  	ProxyFactoryKey string
    84  	adaptiveService bool
    85  	metricsEnable   bool // whether append metrics filter to filter chain
    86  	unexported      *atomic.Bool
    87  	exported        *atomic.Bool
    88  	export          bool // a flag to control whether the current service should export or not
    89  	rpcService      common.RPCService
    90  	cacheMutex      sync.Mutex
    91  	cacheProtocol   protocol.Protocol
    92  	exportersLock   sync.Mutex
    93  	exporters       []protocol.Exporter
    94  
    95  	metadataType string
    96  }
    97  
    98  // Prefix returns dubbo.service.${InterfaceName}.
    99  func (s *ServiceConfig) Prefix() string {
   100  	return strings.Join([]string{constant.ServiceConfigPrefix, s.id}, ".")
   101  }
   102  
   103  func (s *ServiceConfig) Init(rc *RootConfig) error {
   104  	if err := initProviderMethodConfig(s); err != nil {
   105  		return err
   106  	}
   107  	if err := defaults.Set(s); err != nil {
   108  		return err
   109  	}
   110  	s.exported = atomic.NewBool(false)
   111  	s.metadataType = rc.Application.MetadataType
   112  	if s.Filter == "" {
   113  		s.Filter = rc.Provider.Filter
   114  	}
   115  	if s.Version == "" {
   116  		s.Version = rc.Application.Version
   117  	}
   118  	if s.Group == "" {
   119  		s.Group = rc.Application.Group
   120  	}
   121  	s.unexported = atomic.NewBool(false)
   122  	if len(s.RCRegistriesMap) == 0 {
   123  		s.RCRegistriesMap = rc.Registries
   124  	}
   125  	if len(s.RCProtocolsMap) == 0 {
   126  		s.RCProtocolsMap = rc.Protocols
   127  	}
   128  	if rc.Provider != nil {
   129  		s.ProxyFactoryKey = rc.Provider.ProxyFactory
   130  	}
   131  	s.RegistryIDs = translateIds(s.RegistryIDs)
   132  	if len(s.RegistryIDs) <= 0 {
   133  		s.RegistryIDs = rc.Provider.RegistryIDs
   134  	}
   135  
   136  	s.ProtocolIDs = translateIds(s.ProtocolIDs)
   137  	if len(s.ProtocolIDs) <= 0 {
   138  		s.ProtocolIDs = rc.Provider.ProtocolIDs
   139  	}
   140  	if len(s.ProtocolIDs) <= 0 {
   141  		for k := range rc.Protocols {
   142  			s.ProtocolIDs = append(s.ProtocolIDs, k)
   143  		}
   144  	}
   145  	if s.TracingKey == "" {
   146  		s.TracingKey = rc.Provider.TracingKey
   147  	}
   148  	if rc.Metric.Enable != nil {
   149  		s.metricsEnable = *rc.Metric.Enable
   150  	}
   151  	err := s.check()
   152  	if err != nil {
   153  		panic(err)
   154  	}
   155  	s.export = true
   156  	return verify(s)
   157  }
   158  
   159  func (s *ServiceConfig) check() error {
   160  	// check if the limiter has been imported
   161  	if s.TpsLimiter != "" {
   162  		_, err := extension.GetTpsLimiter(s.TpsLimiter)
   163  		if err != nil {
   164  			panic(err)
   165  		}
   166  	}
   167  	if s.TpsLimitStrategy != "" {
   168  		_, err := extension.GetTpsLimitStrategyCreator(s.TpsLimitStrategy)
   169  		if err != nil {
   170  			panic(err)
   171  		}
   172  	}
   173  	if s.TpsLimitRejectedHandler != "" {
   174  		_, err := extension.GetRejectedExecutionHandler(s.TpsLimitRejectedHandler)
   175  		if err != nil {
   176  			panic(err)
   177  		}
   178  	}
   179  
   180  	if s.TpsLimitInterval != "" {
   181  		tpsLimitInterval, err := strconv.ParseInt(s.TpsLimitInterval, 0, 0)
   182  		if err != nil {
   183  			return fmt.Errorf("[ServiceConfig] Cannot parse the configuration tps.limit.interval for service %s, please check your configuration", s.Interface)
   184  		}
   185  		if tpsLimitInterval < 0 {
   186  			return fmt.Errorf("[ServiceConfig] The configuration tps.limit.interval for service %s must be positive, please check your configuration", s.Interface)
   187  		}
   188  	}
   189  
   190  	if s.TpsLimitRate != "" {
   191  		tpsLimitRate, err := strconv.ParseInt(s.TpsLimitRate, 0, 0)
   192  		if err != nil {
   193  			return fmt.Errorf("[ServiceConfig] Cannot parse the configuration tps.limit.rate for service %s, please check your configuration", s.Interface)
   194  		}
   195  		if tpsLimitRate < 0 {
   196  			return fmt.Errorf("[ServiceConfig] The configuration tps.limit.rate for service %s must be positive, please check your configuration", s.Interface)
   197  		}
   198  	}
   199  	return nil
   200  }
   201  
   202  // InitExported will set exported as false atom bool
   203  func (s *ServiceConfig) InitExported() {
   204  	s.exported = atomic.NewBool(false)
   205  }
   206  
   207  // IsExport will return whether the service config is exported or not
   208  func (s *ServiceConfig) IsExport() bool {
   209  	return s.exported.Load()
   210  }
   211  
   212  // Get Random Port
   213  func getRandomPort(protocolConfigs []*ProtocolConfig) *list.List {
   214  	ports := list.New()
   215  	for _, proto := range protocolConfigs {
   216  		if port, err := strconv.Atoi(proto.Port); err != nil {
   217  			logger.Infof(
   218  				"%s will be assgined to a random port, since the port is an invalid number",
   219  				proto.Name,
   220  			)
   221  		} else if port > 0 {
   222  			continue
   223  		}
   224  
   225  		tcp, err := gxnet.ListenOnTCPRandomPort(proto.Ip)
   226  		if err != nil {
   227  			panic(perrors.New(fmt.Sprintf("Get tcp port error, err is {%v}", err)))
   228  		}
   229  		defer tcp.Close()
   230  		ports.PushBack(strings.Split(tcp.Addr().String(), ":")[1])
   231  	}
   232  	return ports
   233  }
   234  
   235  // Export exports the service
   236  func (s *ServiceConfig) Export() error {
   237  	// TODO: delay export
   238  	if s.unexported != nil && s.unexported.Load() {
   239  		err := perrors.Errorf("The service %v has already unexported!", s.Interface)
   240  		logger.Errorf(err.Error())
   241  		return err
   242  	}
   243  	if s.exported != nil && s.exported.Load() {
   244  		logger.Warnf("The service %v has already exported!", s.Interface)
   245  		return nil
   246  	}
   247  
   248  	regUrls := make([]*common.URL, 0)
   249  	if !s.NotRegister {
   250  		regUrls = loadRegistries(s.RegistryIDs, s.RCRegistriesMap, common.PROVIDER)
   251  	}
   252  
   253  	urlMap := s.getUrlMap()
   254  	protocolConfigs := loadProtocol(s.ProtocolIDs, s.RCProtocolsMap)
   255  	if len(protocolConfigs) == 0 {
   256  		logger.Warnf("The service %v's '%v' protocols don't has right protocolConfigs, Please check your configuration center and transfer protocol ", s.Interface, s.ProtocolIDs)
   257  		return nil
   258  	}
   259  
   260  	ports := getRandomPort(protocolConfigs)
   261  	nextPort := ports.Front()
   262  	proxyFactory := extension.GetProxyFactory(s.ProxyFactoryKey)
   263  	for _, proto := range protocolConfigs {
   264  		// registry the service reflect
   265  		methods, err := common.ServiceMap.Register(s.Interface, proto.Name, s.Group, s.Version, s.rpcService)
   266  		if err != nil {
   267  			formatErr := perrors.Errorf("The service %v export the protocol %v error! Error message is %v.",
   268  				s.Interface, proto.Name, err.Error())
   269  			logger.Errorf(formatErr.Error())
   270  			return formatErr
   271  		}
   272  
   273  		port := proto.Port
   274  		if num, err := strconv.Atoi(proto.Port); err != nil || num <= 0 {
   275  			port = nextPort.Value.(string)
   276  			nextPort = nextPort.Next()
   277  		}
   278  		ivkURL := common.NewURLWithOptions(
   279  			common.WithPath(s.Interface),
   280  			common.WithProtocol(proto.Name),
   281  			common.WithIp(proto.Ip),
   282  			common.WithPort(port),
   283  			common.WithParams(urlMap),
   284  			common.WithParamsValue(constant.BeanNameKey, s.id),
   285  			//common.WithParamsValue(constant.SslEnabledKey, strconv.FormatBool(config.GetSslEnabled())),
   286  			common.WithMethods(strings.Split(methods, ",")),
   287  			common.WithToken(s.Token),
   288  			common.WithParamsValue(constant.MetadataTypeKey, s.metadataType),
   289  			// fix https://github.com/apache/dubbo-go/issues/2176
   290  			common.WithParamsValue(constant.MaxServerSendMsgSize, proto.MaxServerSendMsgSize),
   291  			common.WithParamsValue(constant.MaxServerRecvMsgSize, proto.MaxServerRecvMsgSize),
   292  		)
   293  		if len(s.Tag) > 0 {
   294  			ivkURL.AddParam(constant.Tagkey, s.Tag)
   295  		}
   296  
   297  		// post process the URL to be exported
   298  		s.postProcessConfig(ivkURL)
   299  		// config post processor may set "export" to false
   300  		if !ivkURL.GetParamBool(constant.ExportKey, true) {
   301  			return nil
   302  		}
   303  
   304  		if len(regUrls) > 0 {
   305  			s.cacheMutex.Lock()
   306  			if s.cacheProtocol == nil {
   307  				logger.Debugf(fmt.Sprintf("First load the registry protocol, url is {%v}!", ivkURL))
   308  				s.cacheProtocol = extension.GetProtocol(constant.RegistryProtocol)
   309  			}
   310  			s.cacheMutex.Unlock()
   311  
   312  			for _, regUrl := range regUrls {
   313  				setRegistrySubURL(ivkURL, regUrl)
   314  				invoker := proxyFactory.GetInvoker(regUrl)
   315  				exporter := s.cacheProtocol.Export(invoker)
   316  				if exporter == nil {
   317  					return perrors.New(fmt.Sprintf("Registry protocol new exporter error, registry is {%v}, url is {%v}", regUrl, ivkURL))
   318  				}
   319  				s.exporters = append(s.exporters, exporter)
   320  			}
   321  		} else {
   322  			if ivkURL.GetParam(constant.InterfaceKey, "") == constant.MetadataServiceName {
   323  				ms, err := extension.GetLocalMetadataService("")
   324  				if err != nil {
   325  					logger.Warnf("export org.apache.dubbo.metadata.MetadataService failed beacause of %s ! pls check if you import _ \"dubbo.apache.org/dubbo-go/v3/metadata/service/local\"", err)
   326  					return nil
   327  				}
   328  				if err := ms.SetMetadataServiceURL(ivkURL); err != nil {
   329  					logger.Warnf("SetMetadataServiceURL error = %s", err)
   330  				}
   331  			}
   332  			invoker := proxyFactory.GetInvoker(ivkURL)
   333  			exporter := extension.GetProtocol(protocolwrapper.FILTER).Export(invoker)
   334  			if exporter == nil {
   335  				return perrors.New(fmt.Sprintf("Filter protocol without registry new exporter error, url is {%v}", ivkURL))
   336  			}
   337  			s.exporters = append(s.exporters, exporter)
   338  		}
   339  		publishServiceDefinition(ivkURL)
   340  	}
   341  	s.exported.Store(true)
   342  	return nil
   343  }
   344  
   345  // setRegistrySubURL set registry sub url is ivkURl
   346  func setRegistrySubURL(ivkURL *common.URL, regUrl *common.URL) {
   347  	ivkURL.AddParam(constant.RegistryKey, regUrl.GetParam(constant.RegistryKey, ""))
   348  	regUrl.SubURL = ivkURL
   349  }
   350  
   351  // loadProtocol filter protocols by ids
   352  func loadProtocol(protocolIds []string, protocols map[string]*ProtocolConfig) []*ProtocolConfig {
   353  	returnProtocols := make([]*ProtocolConfig, 0, len(protocols))
   354  	for _, v := range protocolIds {
   355  		for k, config := range protocols {
   356  			if v == k {
   357  				returnProtocols = append(returnProtocols, config)
   358  			}
   359  		}
   360  	}
   361  	return returnProtocols
   362  }
   363  
   364  // Unexport will call unexport of all exporters service config exported
   365  func (s *ServiceConfig) Unexport() {
   366  	if !s.exported.Load() {
   367  		return
   368  	}
   369  	if s.unexported.Load() {
   370  		return
   371  	}
   372  
   373  	func() {
   374  		s.exportersLock.Lock()
   375  		defer s.exportersLock.Unlock()
   376  		for _, exporter := range s.exporters {
   377  			exporter.UnExport()
   378  		}
   379  		s.exporters = nil
   380  	}()
   381  
   382  	s.exported.Store(false)
   383  	s.unexported.Store(true)
   384  }
   385  
   386  // Implement only store the @s and return
   387  func (s *ServiceConfig) Implement(rpcService common.RPCService) {
   388  	s.rpcService = rpcService
   389  }
   390  
   391  func (s *ServiceConfig) getUrlMap() url.Values {
   392  	urlMap := url.Values{}
   393  	// first set user params
   394  	for k, v := range s.Params {
   395  		urlMap.Set(k, v)
   396  	}
   397  	urlMap.Set(constant.InterfaceKey, s.Interface)
   398  	urlMap.Set(constant.TimestampKey, strconv.FormatInt(time.Now().Unix(), 10))
   399  	urlMap.Set(constant.ClusterKey, s.Cluster)
   400  	urlMap.Set(constant.LoadbalanceKey, s.Loadbalance)
   401  	urlMap.Set(constant.WarmupKey, s.Warmup)
   402  	urlMap.Set(constant.RetriesKey, s.Retries)
   403  	if s.Group != "" {
   404  		urlMap.Set(constant.GroupKey, s.Group)
   405  	}
   406  	if s.Version != "" {
   407  		urlMap.Set(constant.VersionKey, s.Version)
   408  	}
   409  	urlMap.Set(constant.RegistryRoleKey, strconv.Itoa(common.PROVIDER))
   410  	urlMap.Set(constant.ReleaseKey, "dubbo-golang-"+constant.Version)
   411  	urlMap.Set(constant.SideKey, (common.RoleType(common.PROVIDER)).Role())
   412  	// todo: move
   413  	urlMap.Set(constant.SerializationKey, s.Serialization)
   414  	// application config info
   415  	ac := GetApplicationConfig()
   416  	urlMap.Set(constant.ApplicationKey, ac.Name)
   417  	urlMap.Set(constant.OrganizationKey, ac.Organization)
   418  	urlMap.Set(constant.NameKey, ac.Name)
   419  	urlMap.Set(constant.ModuleKey, ac.Module)
   420  	urlMap.Set(constant.AppVersionKey, ac.Version)
   421  	urlMap.Set(constant.OwnerKey, ac.Owner)
   422  	urlMap.Set(constant.EnvironmentKey, ac.Environment)
   423  
   424  	// filter
   425  	var filters string
   426  	if s.Filter == "" {
   427  		filters = constant.DefaultServiceFilters
   428  	} else {
   429  		filters = s.Filter
   430  	}
   431  	if s.adaptiveService {
   432  		filters += fmt.Sprintf(",%s", constant.AdaptiveServiceProviderFilterKey)
   433  	}
   434  	if s.metricsEnable {
   435  		filters += fmt.Sprintf(",%s", constant.MetricsFilterKey)
   436  	}
   437  	urlMap.Set(constant.ServiceFilterKey, filters)
   438  
   439  	// filter special config
   440  	urlMap.Set(constant.AccessLogFilterKey, s.AccessLog)
   441  	// tps limiter
   442  	urlMap.Set(constant.TPSLimitStrategyKey, s.TpsLimitStrategy)
   443  	urlMap.Set(constant.TPSLimitIntervalKey, s.TpsLimitInterval)
   444  	urlMap.Set(constant.TPSLimitRateKey, s.TpsLimitRate)
   445  	urlMap.Set(constant.TPSLimiterKey, s.TpsLimiter)
   446  	urlMap.Set(constant.TPSRejectedExecutionHandlerKey, s.TpsLimitRejectedHandler)
   447  	urlMap.Set(constant.TracingConfigKey, s.TracingKey)
   448  
   449  	// execute limit filter
   450  	urlMap.Set(constant.ExecuteLimitKey, s.ExecuteLimit)
   451  	urlMap.Set(constant.ExecuteRejectedExecutionHandlerKey, s.ExecuteLimitRejectedHandler)
   452  
   453  	// auth filter
   454  	urlMap.Set(constant.ServiceAuthKey, s.Auth)
   455  	urlMap.Set(constant.ParameterSignatureEnableKey, s.ParamSign)
   456  
   457  	// whether to export or not
   458  	urlMap.Set(constant.ExportKey, strconv.FormatBool(s.export))
   459  	urlMap.Set(constant.PIDKey, fmt.Sprintf("%d", os.Getpid()))
   460  
   461  	for _, v := range s.Methods {
   462  		prefix := "methods." + v.Name + "."
   463  		urlMap.Set(prefix+constant.LoadbalanceKey, v.LoadBalance)
   464  		urlMap.Set(prefix+constant.RetriesKey, v.Retries)
   465  		urlMap.Set(prefix+constant.WeightKey, strconv.FormatInt(v.Weight, 10))
   466  
   467  		urlMap.Set(prefix+constant.TPSLimitStrategyKey, v.TpsLimitStrategy)
   468  		urlMap.Set(prefix+constant.TPSLimitIntervalKey, v.TpsLimitInterval)
   469  		urlMap.Set(prefix+constant.TPSLimitRateKey, v.TpsLimitRate)
   470  
   471  		urlMap.Set(constant.ExecuteLimitKey, v.ExecuteLimit)
   472  		urlMap.Set(constant.ExecuteRejectedExecutionHandlerKey, v.ExecuteLimitRejectedHandler)
   473  	}
   474  
   475  	return urlMap
   476  }
   477  
   478  // GetExportedUrls will return the url in service config's exporter
   479  func (s *ServiceConfig) GetExportedUrls() []*common.URL {
   480  	if s.exported.Load() {
   481  		var urls []*common.URL
   482  		for _, exporter := range s.exporters {
   483  			urls = append(urls, exporter.GetInvoker().GetURL())
   484  		}
   485  		return urls
   486  	}
   487  	return nil
   488  }
   489  
   490  // postProcessConfig asks registered ConfigPostProcessor to post-process the current ServiceConfig.
   491  func (s *ServiceConfig) postProcessConfig(url *common.URL) {
   492  	for _, p := range extension.GetConfigPostProcessors() {
   493  		p.PostProcessServiceConfig(url)
   494  	}
   495  }
   496  
   497  // newEmptyServiceConfig returns default ServiceConfig
   498  func newEmptyServiceConfig() *ServiceConfig {
   499  	newServiceConfig := &ServiceConfig{
   500  		unexported:      atomic.NewBool(false),
   501  		exported:        atomic.NewBool(false),
   502  		export:          true,
   503  		RCProtocolsMap:  make(map[string]*ProtocolConfig),
   504  		RCRegistriesMap: make(map[string]*RegistryConfig),
   505  	}
   506  	newServiceConfig.Params = make(map[string]string)
   507  	newServiceConfig.Methods = make([]*MethodConfig, 0, 8)
   508  	return newServiceConfig
   509  }
   510  
   511  type ServiceConfigBuilder struct {
   512  	serviceConfig *ServiceConfig
   513  }
   514  
   515  func NewServiceConfigBuilder() *ServiceConfigBuilder {
   516  	return &ServiceConfigBuilder{serviceConfig: newEmptyServiceConfig()}
   517  }
   518  
   519  func (pcb *ServiceConfigBuilder) SetRegistryIDs(registryIDs ...string) *ServiceConfigBuilder {
   520  	pcb.serviceConfig.RegistryIDs = registryIDs
   521  	return pcb
   522  }
   523  
   524  func (pcb *ServiceConfigBuilder) SetProtocolIDs(protocolIDs ...string) *ServiceConfigBuilder {
   525  	pcb.serviceConfig.ProtocolIDs = protocolIDs
   526  	return pcb
   527  }
   528  
   529  func (pcb *ServiceConfigBuilder) SetInterface(interfaceName string) *ServiceConfigBuilder {
   530  	pcb.serviceConfig.Interface = interfaceName
   531  	return pcb
   532  }
   533  
   534  func (pcb *ServiceConfigBuilder) SetMetadataType(setMetadataType string) *ServiceConfigBuilder {
   535  	pcb.serviceConfig.metadataType = setMetadataType
   536  	return pcb
   537  }
   538  
   539  func (pcb *ServiceConfigBuilder) SetLoadBalancce(lb string) *ServiceConfigBuilder {
   540  	pcb.serviceConfig.Loadbalance = lb
   541  	return pcb
   542  }
   543  
   544  func (pcb *ServiceConfigBuilder) SetWarmUpTie(warmUp string) *ServiceConfigBuilder {
   545  	pcb.serviceConfig.Warmup = warmUp
   546  	return pcb
   547  }
   548  
   549  func (pcb *ServiceConfigBuilder) SetCluster(cluster string) *ServiceConfigBuilder {
   550  	pcb.serviceConfig.Cluster = cluster
   551  	return pcb
   552  }
   553  
   554  func (pcb *ServiceConfigBuilder) AddRCProtocol(protocolName string, protocolConfig *ProtocolConfig) *ServiceConfigBuilder {
   555  	pcb.serviceConfig.RCProtocolsMap[protocolName] = protocolConfig
   556  	return pcb
   557  }
   558  
   559  func (pcb *ServiceConfigBuilder) AddRCRegistry(registryName string, registryConfig *RegistryConfig) *ServiceConfigBuilder {
   560  	pcb.serviceConfig.RCRegistriesMap[registryName] = registryConfig
   561  	return pcb
   562  }
   563  
   564  func (pcb *ServiceConfigBuilder) SetGroup(group string) *ServiceConfigBuilder {
   565  	pcb.serviceConfig.Group = group
   566  	return pcb
   567  }
   568  func (pcb *ServiceConfigBuilder) SetVersion(version string) *ServiceConfigBuilder {
   569  	pcb.serviceConfig.Version = version
   570  	return pcb
   571  }
   572  
   573  func (pcb *ServiceConfigBuilder) SetProxyFactoryKey(proxyFactoryKey string) *ServiceConfigBuilder {
   574  	pcb.serviceConfig.ProxyFactoryKey = proxyFactoryKey
   575  	return pcb
   576  }
   577  
   578  func (pcb *ServiceConfigBuilder) SetRPCService(service common.RPCService) *ServiceConfigBuilder {
   579  	pcb.serviceConfig.rpcService = service
   580  	return pcb
   581  }
   582  
   583  func (pcb *ServiceConfigBuilder) SetSerialization(serialization string) *ServiceConfigBuilder {
   584  	pcb.serviceConfig.Serialization = serialization
   585  	return pcb
   586  }
   587  
   588  func (pcb *ServiceConfigBuilder) SetServiceID(id string) *ServiceConfigBuilder {
   589  	pcb.serviceConfig.id = id
   590  	return pcb
   591  }
   592  
   593  func (pcb *ServiceConfigBuilder) SetNotRegister(notRegister bool) *ServiceConfigBuilder {
   594  	pcb.serviceConfig.NotRegister = notRegister
   595  	return pcb
   596  }
   597  
   598  func (pcb *ServiceConfigBuilder) Build() *ServiceConfig {
   599  	return pcb.serviceConfig
   600  }