dubbo.apache.org/dubbo-go/v3@v3.1.1/config/consumer_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 "fmt" 22 "strings" 23 "time" 24 ) 25 26 import ( 27 "github.com/creasty/defaults" 28 29 "github.com/dubbogo/gost/log/logger" 30 31 tripleConstant "github.com/dubbogo/triple/pkg/common/constant" 32 ) 33 34 import ( 35 "dubbo.apache.org/dubbo-go/v3/common" 36 "dubbo.apache.org/dubbo-go/v3/common/constant" 37 ) 38 39 const ( 40 MaxWheelTimeSpan = 900e9 // 900s, 15 minute 41 ) 42 43 // ConsumerConfig is Consumer default configuration 44 type ConsumerConfig struct { 45 Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"` 46 RegistryIDs []string `yaml:"registry-ids" json:"registry-ids,omitempty" property:"registry-ids"` 47 Protocol string `yaml:"protocol" json:"protocol,omitempty" property:"protocol"` 48 RequestTimeout string `default:"3s" yaml:"request-timeout" json:"request-timeout,omitempty" property:"request-timeout"` 49 ProxyFactory string `default:"default" yaml:"proxy" json:"proxy,omitempty" property:"proxy"` 50 Check bool `yaml:"check" json:"check,omitempty" property:"check"` 51 AdaptiveService bool `default:"false" yaml:"adaptive-service" json:"adaptive-service" property:"adaptive-service"` 52 References map[string]*ReferenceConfig `yaml:"references" json:"references,omitempty" property:"references"` 53 TracingKey string `yaml:"tracing-key" json:"tracing-key" property:"tracing-key"` 54 FilterConf interface{} `yaml:"filter-conf" json:"filter-conf,omitempty" property:"filter-conf"` 55 MaxWaitTimeForServiceDiscovery string `default:"3s" yaml:"max-wait-time-for-service-discovery" json:"max-wait-time-for-service-discovery,omitempty" property:"max-wait-time-for-service-discovery"` 56 MeshEnabled bool `yaml:"mesh-enabled" json:"mesh-enabled,omitempty" property:"mesh-enabled"` 57 rootConfig *RootConfig 58 } 59 60 // Prefix dubbo.consumer 61 func (ConsumerConfig) Prefix() string { 62 return constant.ConsumerConfigPrefix 63 } 64 65 func (cc *ConsumerConfig) Init(rc *RootConfig) error { 66 if cc == nil { 67 return nil 68 } 69 70 buildDebugMsg := func() string { 71 if len(cc.References) == 0 { 72 return "empty" 73 } 74 consumerNames := make([]string, 0, len(cc.References)) 75 for k := range cc.References { 76 consumerNames = append(consumerNames, k) 77 } 78 return strings.Join(consumerNames, ", ") 79 } 80 logger.Debugf("Registered consumer clients are %v", buildDebugMsg()) 81 82 cc.RegistryIDs = translateIds(cc.RegistryIDs) 83 if len(cc.RegistryIDs) <= 0 { 84 cc.RegistryIDs = rc.getRegistryIds() 85 } 86 if cc.TracingKey == "" && len(rc.Tracing) > 0 { 87 for k := range rc.Tracing { 88 cc.TracingKey = k 89 break 90 } 91 } 92 for key, referenceConfig := range cc.References { 93 if referenceConfig.InterfaceName == "" { 94 reference := GetConsumerService(key) 95 // try to use interface name defined by pb 96 triplePBService, ok := reference.(common.TriplePBService) 97 if !ok { 98 logger.Errorf("Dubbo-go cannot get interface name with reference = %s."+ 99 "Please run the command 'go install github.com/dubbogo/dubbogo-cli/cmd/protoc-gen-go-triple@latest' to get the latest "+ 100 "protoc-gen-go-triple, and then re-generate your pb file again by this tool."+ 101 "If you are not using pb serialization, please set 'interfaceName' field in reference config to let dubbogo get the interface name.", key) 102 continue 103 } else { 104 // use interface name defined by pb 105 referenceConfig.InterfaceName = triplePBService.XXX_InterfaceName() 106 } 107 } 108 if err := referenceConfig.Init(rc); err != nil { 109 return err 110 } 111 } 112 if err := defaults.Set(cc); err != nil { 113 return err 114 } 115 if err := verify(cc); err != nil { 116 return err 117 } 118 119 cc.rootConfig = rc 120 return nil 121 } 122 123 func (cc *ConsumerConfig) Load() { 124 for registeredTypeName, refRPCService := range GetConsumerServiceMap() { 125 refConfig, ok := cc.References[registeredTypeName] 126 if !ok { 127 // not found configuration, now new a configuration with default. 128 refConfig = NewReferenceConfigBuilder().SetProtocol(tripleConstant.TRIPLE).Build() 129 triplePBService, ok := refRPCService.(common.TriplePBService) 130 if !ok { 131 logger.Errorf("Dubbo-go cannot get interface name with registeredTypeName = %s."+ 132 "Please run the command 'go install github.com/dubbogo/dubbogo-cli/cmd/protoc-gen-go-triple@latest' to get the latest "+ 133 "protoc-gen-go-triple, and then re-generate your pb file again by this tool."+ 134 "If you are not using pb serialization, please set 'interfaceName' field in reference config to let dubbogo get the interface name.", registeredTypeName) 135 continue 136 } else { 137 // use interface name defined by pb 138 refConfig.InterfaceName = triplePBService.XXX_InterfaceName() 139 } 140 if err := refConfig.Init(rootConfig); err != nil { 141 logger.Errorf(fmt.Sprintf("reference with registeredTypeName = %s init failed! err: %#v", registeredTypeName, err)) 142 continue 143 } 144 } 145 refConfig.id = registeredTypeName 146 refConfig.Refer(refRPCService) 147 refConfig.Implement(refRPCService) 148 } 149 150 var maxWait int 151 152 if maxWaitDuration, err := time.ParseDuration(cc.MaxWaitTimeForServiceDiscovery); err != nil { 153 logger.Warnf("Invalid consumer max wait time for service discovery: %s, fallback to 3s", cc.MaxWaitTimeForServiceDiscovery) 154 maxWait = 3 155 } else { 156 maxWait = int(maxWaitDuration.Seconds()) 157 } 158 159 // wait for invoker is available, if wait over default 3s, then panic 160 var count int 161 for { 162 checkok := true 163 for key, ref := range cc.References { 164 if (ref.Check != nil && *ref.Check && GetProviderService(key) == nil) || 165 (ref.Check == nil && cc.Check && GetProviderService(key) == nil) || 166 (ref.Check == nil && GetProviderService(key) == nil) { // default to true 167 168 if ref.invoker != nil && !ref.invoker.IsAvailable() { 169 checkok = false 170 count++ 171 if count > maxWait { 172 errMsg := fmt.Sprintf("No provider available of the service %v.please check configuration.", ref.InterfaceName) 173 logger.Error(errMsg) 174 panic(errMsg) 175 } 176 time.Sleep(time.Second * 1) 177 break 178 } 179 if ref.invoker == nil { 180 logger.Warnf("The interface %s invoker not exist, may you should check your interface config.", ref.InterfaceName) 181 } 182 } 183 } 184 if checkok { 185 break 186 } 187 } 188 } 189 190 // SetConsumerConfig sets consumerConfig by @c 191 func SetConsumerConfig(c ConsumerConfig) { 192 rootConfig.Consumer = &c 193 } 194 195 func newEmptyConsumerConfig() *ConsumerConfig { 196 newConsumerConfig := &ConsumerConfig{ 197 References: make(map[string]*ReferenceConfig, 8), 198 RequestTimeout: "3s", 199 Check: true, 200 } 201 return newConsumerConfig 202 } 203 204 type ConsumerConfigBuilder struct { 205 consumerConfig *ConsumerConfig 206 } 207 208 func NewConsumerConfigBuilder() *ConsumerConfigBuilder { 209 return &ConsumerConfigBuilder{consumerConfig: newEmptyConsumerConfig()} 210 } 211 212 func (ccb *ConsumerConfigBuilder) SetFilter(filter string) *ConsumerConfigBuilder { 213 ccb.consumerConfig.Filter = filter 214 return ccb 215 } 216 217 func (ccb *ConsumerConfigBuilder) SetRegistryIDs(RegistryIDs ...string) *ConsumerConfigBuilder { 218 ccb.consumerConfig.RegistryIDs = RegistryIDs 219 return ccb 220 } 221 222 func (ccb *ConsumerConfigBuilder) SetRequestTimeout(requestTimeout string) *ConsumerConfigBuilder { 223 ccb.consumerConfig.RequestTimeout = requestTimeout 224 return ccb 225 } 226 227 func (ccb *ConsumerConfigBuilder) SetMaxWaitTimeForServiceDiscovery(maxWaitTimeForServiceDiscovery string) *ConsumerConfigBuilder { 228 ccb.consumerConfig.MaxWaitTimeForServiceDiscovery = maxWaitTimeForServiceDiscovery 229 return ccb 230 } 231 232 func (ccb *ConsumerConfigBuilder) SetProxyFactory(proxyFactory string) *ConsumerConfigBuilder { 233 ccb.consumerConfig.ProxyFactory = proxyFactory 234 return ccb 235 } 236 237 func (ccb *ConsumerConfigBuilder) SetCheck(check bool) *ConsumerConfigBuilder { 238 ccb.consumerConfig.Check = check 239 return ccb 240 } 241 242 func (ccb *ConsumerConfigBuilder) AddReference(referenceKey string, referenceConfig *ReferenceConfig) *ConsumerConfigBuilder { 243 ccb.consumerConfig.References[referenceKey] = referenceConfig 244 return ccb 245 } 246 247 func (ccb *ConsumerConfigBuilder) SetReferences(references map[string]*ReferenceConfig) *ConsumerConfigBuilder { 248 ccb.consumerConfig.References = references 249 return ccb 250 } 251 252 func (ccb *ConsumerConfigBuilder) SetFilterConf(filterConf interface{}) *ConsumerConfigBuilder { 253 ccb.consumerConfig.FilterConf = filterConf 254 return ccb 255 } 256 257 func (ccb *ConsumerConfigBuilder) SetMeshEnabled(meshEnabled bool) *ConsumerConfigBuilder { 258 ccb.consumerConfig.MeshEnabled = meshEnabled 259 return ccb 260 } 261 262 func (ccb *ConsumerConfigBuilder) SetRootConfig(rootConfig *RootConfig) *ConsumerConfigBuilder { 263 ccb.consumerConfig.rootConfig = rootConfig 264 return ccb 265 } 266 267 func (ccb *ConsumerConfigBuilder) Build() *ConsumerConfig { 268 return ccb.consumerConfig 269 } 270 271 // DynamicUpdateProperties dynamically update properties. 272 func (cc *ConsumerConfig) DynamicUpdateProperties(newConsumerConfig *ConsumerConfig) { 273 if newConsumerConfig != nil && newConsumerConfig.RequestTimeout != cc.RequestTimeout { 274 cc.RequestTimeout = newConsumerConfig.RequestTimeout 275 logger.Infof("ConsumerConfig's RequestTimeout was dynamically updated, new value:%v", cc.RequestTimeout) 276 } 277 }