dubbo.apache.org/dubbo-go/v3@v3.1.1/registry/protocol/protocol.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 protocol 19 20 import ( 21 "context" 22 "strings" 23 "sync" 24 "time" 25 ) 26 27 import ( 28 gxset "github.com/dubbogo/gost/container/set" 29 "github.com/dubbogo/gost/log/logger" 30 31 perrors "github.com/pkg/errors" 32 ) 33 34 import ( 35 "dubbo.apache.org/dubbo-go/v3/common" 36 "dubbo.apache.org/dubbo-go/v3/common/constant" 37 "dubbo.apache.org/dubbo-go/v3/common/extension" 38 "dubbo.apache.org/dubbo-go/v3/config" 39 "dubbo.apache.org/dubbo-go/v3/config_center" 40 _ "dubbo.apache.org/dubbo-go/v3/config_center/configurator" 41 "dubbo.apache.org/dubbo-go/v3/protocol" 42 "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3/health" 43 "dubbo.apache.org/dubbo-go/v3/protocol/protocolwrapper" 44 "dubbo.apache.org/dubbo-go/v3/registry" 45 "dubbo.apache.org/dubbo-go/v3/remoting" 46 ) 47 48 var ( 49 regProtocol *registryProtocol 50 once sync.Once 51 reserveParams = []string{ 52 "application", "codec", "exchanger", "serialization", "cluster", "connections", "deprecated", "group", 53 "loadbalance", "mock", "path", "timeout", "token", "version", "warmup", "weight", "timestamp", "dubbo", 54 "release", "interface", "registry.role", 55 } 56 ) 57 58 type registryProtocol struct { 59 // Registry Map<RegistryAddress, Registry> 60 registries *sync.Map 61 // To solve the problem of RMI repeated exposure port conflicts, 62 // the services that have been exposed are no longer exposed. 63 // providerurl <--> exporter 64 bounds *sync.Map 65 overrideListeners *sync.Map 66 serviceConfigurationListeners *sync.Map 67 providerConfigurationListener *providerConfigurationListener 68 once sync.Once 69 } 70 71 func init() { 72 extension.SetProtocol(constant.RegistryProtocol, GetProtocol) 73 } 74 75 func newRegistryProtocol() *registryProtocol { 76 return ®istryProtocol{ 77 registries: &sync.Map{}, 78 bounds: &sync.Map{}, 79 } 80 } 81 82 func (proto *registryProtocol) getRegistry(registryUrl *common.URL) registry.Registry { 83 var err error 84 reg, loaded := proto.registries.Load(registryUrl.PrimitiveURL) 85 if !loaded { 86 reg, err = extension.GetRegistry(registryUrl.Protocol, registryUrl) 87 if err != nil { 88 logger.Errorf("Registry can not connect success, program is going to panic.Error message is %s", err.Error()) 89 panic(err) 90 } 91 proto.registries.Store(registryUrl.PrimitiveURL, reg) 92 } 93 return reg.(registry.Registry) 94 } 95 96 func getCacheKey(invoker protocol.Invoker) string { 97 url := getProviderUrl(invoker) 98 delKeys := gxset.NewSet("dynamic", "enabled") 99 return url.CloneExceptParams(delKeys).String() 100 } 101 102 func getUrlToRegistry(providerUrl *common.URL, registryUrl *common.URL) *common.URL { 103 if registryUrl.GetParamBool("simplified", false) { 104 return providerUrl.CloneWithParams(reserveParams) 105 } else { 106 return filterHideKey(providerUrl) 107 } 108 } 109 110 // filterHideKey filter the parameters that do not need to be output in url(Starting with .) 111 func filterHideKey(url *common.URL) *common.URL { 112 // be careful params maps in url is map type 113 removeSet := gxset.NewSet() 114 for k := range url.GetParams() { 115 if strings.HasPrefix(k, ".") { 116 removeSet.Add(k) 117 } 118 } 119 return url.CloneExceptParams(removeSet) 120 } 121 122 func (proto *registryProtocol) initConfigurationListeners() { 123 proto.overrideListeners = &sync.Map{} 124 proto.serviceConfigurationListeners = &sync.Map{} 125 proto.providerConfigurationListener = newProviderConfigurationListener(proto.overrideListeners) 126 } 127 128 // nolint 129 func (proto *registryProtocol) GetRegistries() []registry.Registry { 130 var rs []registry.Registry 131 proto.registries.Range(func(_, v interface{}) bool { 132 if r, ok := v.(registry.Registry); ok { 133 rs = append(rs, r) 134 } 135 return true 136 }) 137 return rs 138 } 139 140 // Refer provider service from registry center 141 func (proto *registryProtocol) Refer(url *common.URL) protocol.Invoker { 142 registryUrl := url 143 serviceUrl := registryUrl.SubURL 144 if registryUrl.Protocol == constant.RegistryProtocol { 145 registryUrl.Protocol = registryUrl.GetParam(constant.RegistryKey, "") 146 } 147 148 reg := proto.getRegistry(url) 149 150 // new registry directory for store service url from registry 151 dic, err := extension.GetDirectoryInstance(registryUrl, reg) 152 if err != nil { 153 logger.Errorf("consumer service %v create registry directory error, error message is %s, and will return nil invoker!", 154 serviceUrl.String(), err.Error()) 155 return nil 156 } 157 158 // This will start a new routine and listen to instance changes. 159 err = dic.Subscribe(registryUrl.SubURL) 160 161 if err != nil { 162 logger.Errorf("consumer service %v register registry %v error, error message is %s", 163 serviceUrl.String(), registryUrl.String(), err.Error()) 164 } 165 166 // new cluster invoker 167 clusterKey := serviceUrl.GetParam(constant.ClusterKey, constant.DefaultCluster) 168 cluster, err := extension.GetCluster(clusterKey) 169 if err != nil { 170 panic(err) 171 } 172 invoker := cluster.Join(dic) 173 return invoker 174 } 175 176 // Export provider service to registry center 177 func (proto *registryProtocol) Export(originInvoker protocol.Invoker) protocol.Exporter { 178 proto.once.Do(func() { 179 proto.initConfigurationListeners() 180 }) 181 registryUrl := getRegistryUrl(originInvoker) 182 providerUrl := getProviderUrl(originInvoker) 183 184 overriderUrl := getSubscribedOverrideUrl(providerUrl) 185 // Deprecated! subscribe to override rules in 2.6.x or before. 186 overrideSubscribeListener := newOverrideSubscribeListener(overriderUrl, originInvoker, proto) 187 proto.overrideListeners.Store(overriderUrl, overrideSubscribeListener) 188 proto.providerConfigurationListener.OverrideUrl(providerUrl) 189 serviceConfigurationListener := newServiceConfigurationListener(overrideSubscribeListener, providerUrl) 190 proto.serviceConfigurationListeners.Store(providerUrl.ServiceKey(), serviceConfigurationListener) 191 serviceConfigurationListener.OverrideUrl(providerUrl) 192 193 // export invoker 194 exporter := proto.doLocalExport(originInvoker, providerUrl) 195 196 // update health status 197 health.SetServingStatusServing(registryUrl.Service()) 198 199 if len(registryUrl.Protocol) > 0 { 200 // url to registry 201 reg := proto.getRegistry(registryUrl) 202 registeredProviderUrl := getUrlToRegistry(providerUrl, registryUrl) 203 204 err := reg.Register(registeredProviderUrl) 205 if err != nil { 206 logger.Errorf("provider service %v register registry %v error, error message is %s", 207 providerUrl.Key(), registryUrl.Key(), err.Error()) 208 return nil 209 } 210 211 go func() { 212 if err := reg.Subscribe(overriderUrl, overrideSubscribeListener); err != nil { 213 logger.Warnf("reg.subscribe(overriderUrl:%v) = error:%v", overriderUrl, err) 214 } 215 }() 216 217 exporter.SetRegisterUrl(registeredProviderUrl) 218 exporter.SetSubscribeUrl(overriderUrl) 219 220 } else { 221 logger.Warnf("provider service %v do not regist to registry %v. possible direct connection provider", 222 providerUrl.Key(), registryUrl.Key()) 223 } 224 225 return exporter 226 } 227 228 func (proto *registryProtocol) doLocalExport(originInvoker protocol.Invoker, providerUrl *common.URL) *exporterChangeableWrapper { 229 key := getCacheKey(originInvoker) 230 cachedExporter, loaded := proto.bounds.Load(key) 231 if !loaded { 232 // new Exporter 233 invokerDelegate := newInvokerDelegate(originInvoker, providerUrl) 234 cachedExporter = newExporterChangeableWrapper(originInvoker, 235 extension.GetProtocol(protocolwrapper.FILTER).Export(invokerDelegate)) 236 proto.bounds.Store(key, cachedExporter) 237 } 238 return cachedExporter.(*exporterChangeableWrapper) 239 } 240 241 func (proto *registryProtocol) reExport(invoker protocol.Invoker, newUrl *common.URL) { 242 key := getCacheKey(invoker) 243 if oldExporter, loaded := proto.bounds.Load(key); loaded { 244 wrappedNewInvoker := newInvokerDelegate(invoker, newUrl) 245 oldExporter.(protocol.Exporter).UnExport() 246 proto.bounds.Delete(key) 247 // oldExporter UnExport function unRegister rpcService from the serviceMap, so need register it again as far as possible 248 if err := registerServiceMap(invoker); err != nil { 249 logger.Error(err.Error()) 250 } 251 proto.Export(wrappedNewInvoker) 252 // TODO: unregister & unsubscribe 253 } 254 } 255 256 func registerServiceMap(invoker protocol.Invoker) error { 257 providerUrl := getProviderUrl(invoker) 258 // the bean.name param of providerUrl is the ServiceConfig id property 259 // such as dubbo://:20000/org.apache.dubbo.UserProvider?bean.name=UserProvider&cluster=failfast... 260 id := providerUrl.GetParam(constant.BeanNameKey, "") 261 262 serviceConfig := config.GetProviderConfig().Services[id] 263 if serviceConfig == nil { 264 s := "reExport can not get serviceConfig" 265 return perrors.New(s) 266 } 267 rpcService := config.GetProviderService(id) 268 if rpcService == nil { 269 s := "reExport can not get RPCService" 270 return perrors.New(s) 271 } 272 273 _, err := common.ServiceMap.Register(serviceConfig.Interface, 274 // FIXME 275 serviceConfig.ProtocolIDs[0], serviceConfig.Group, 276 serviceConfig.Version, rpcService) 277 if err != nil { 278 s := "reExport can not re register ServiceMap. Error message is " + err.Error() 279 return perrors.New(s) 280 } 281 return nil 282 } 283 284 type overrideSubscribeListener struct { 285 url *common.URL 286 originInvoker protocol.Invoker 287 protocol *registryProtocol 288 configurator config_center.Configurator 289 } 290 291 func newOverrideSubscribeListener(overriderUrl *common.URL, invoker protocol.Invoker, proto *registryProtocol) *overrideSubscribeListener { 292 return &overrideSubscribeListener{url: overriderUrl, originInvoker: invoker, protocol: proto} 293 } 294 295 // Notify will be triggered when a service change notification is received. 296 func (nl *overrideSubscribeListener) Notify(event *registry.ServiceEvent) { 297 if isMatched(event.Service, nl.url) && event.Action == remoting.EventTypeAdd { 298 nl.configurator = extension.GetDefaultConfigurator(event.Service) 299 nl.doOverrideIfNecessary() 300 } 301 } 302 303 func (nl *overrideSubscribeListener) NotifyAll(events []*registry.ServiceEvent, callback func()) { 304 defer callback() 305 if len(events) == 0 { 306 return 307 } 308 for _, e := range events { 309 nl.Notify(e) 310 } 311 } 312 313 func (nl *overrideSubscribeListener) doOverrideIfNecessary() { 314 providerUrl := getProviderUrl(nl.originInvoker) 315 key := getCacheKey(nl.originInvoker) 316 if exporter, ok := nl.protocol.bounds.Load(key); ok { 317 currentUrl := exporter.(protocol.Exporter).GetInvoker().GetURL() 318 // Compatible with the 2.6.x 319 if nl.configurator != nil { 320 nl.configurator.Configure(providerUrl) 321 } 322 // provider application level management in 2.7.x 323 for _, v := range nl.protocol.providerConfigurationListener.Configurators() { 324 v.Configure(providerUrl) 325 } 326 // provider service level management in 2.7.x 327 if serviceListener, ok := nl.protocol.serviceConfigurationListeners.Load(providerUrl.ServiceKey()); ok { 328 listener := serviceListener.(*serviceConfigurationListener) 329 for _, v := range listener.Configurators() { 330 v.Configure(providerUrl) 331 } 332 } 333 334 if currentUrl.String() != providerUrl.String() { 335 newRegUrl := nl.originInvoker.GetURL().Clone() 336 setProviderUrl(newRegUrl, providerUrl) 337 nl.protocol.reExport(nl.originInvoker, newRegUrl) 338 } 339 } 340 } 341 342 func isMatched(providerUrl *common.URL, consumerUrl *common.URL) bool { 343 // Compatible with the 2.6.x 344 if len(providerUrl.GetParam(constant.CategoryKey, "")) == 0 && 345 providerUrl.Protocol == constant.OverrideProtocol { 346 providerUrl.AddParam(constant.CategoryKey, constant.ConfiguratorsCategory) 347 } 348 consumerInterface := consumerUrl.GetParam(constant.InterfaceKey, consumerUrl.Path) 349 providerInterface := providerUrl.GetParam(constant.InterfaceKey, providerUrl.Path) 350 351 if !(constant.AnyValue == consumerInterface || 352 constant.AnyValue == providerInterface || 353 providerInterface == consumerInterface) { 354 return false 355 } 356 357 if !isMatchCategory(providerUrl.GetParam(constant.CategoryKey, constant.DefaultCategory), 358 consumerUrl.GetParam(constant.CategoryKey, constant.DefaultCategory)) { 359 return false 360 } 361 362 if !providerUrl.GetParamBool(constant.EnabledKey, true) && 363 consumerUrl.GetParam(constant.EnabledKey, "") != constant.AnyValue { 364 return false 365 } 366 consumerGroup := consumerUrl.GetParam(constant.GroupKey, "") 367 consumerVersion := consumerUrl.GetParam(constant.VersionKey, "") 368 consumerClassifier := consumerUrl.GetParam(constant.ClassifierKey, "") 369 370 providerGroup := providerUrl.GetParam(constant.GroupKey, "") 371 providerVersion := providerUrl.GetParam(constant.VersionKey, "") 372 providerClassifier := providerUrl.GetParam(constant.ClassifierKey, "") 373 // todo: public static boolean isContains(String values, String value) { 374 // return isNotEmpty(values) && isContains(CommaSplitPattern.split(values), value); 375 // } 376 return (consumerGroup == constant.AnyValue || consumerGroup == providerGroup || 377 strings.Contains(consumerGroup, providerGroup)) && (consumerVersion == constant.AnyValue || 378 consumerVersion == providerVersion) && (len(consumerClassifier) == 0 || 379 consumerClassifier == constant.AnyValue || consumerClassifier == providerClassifier) 380 } 381 382 func isMatchCategory(category string, categories string) bool { 383 if len(categories) == 0 { 384 return category == constant.DefaultCategory 385 } else if strings.Contains(categories, constant.AnyValue) { 386 return true 387 } else if strings.Contains(categories, constant.RemoveValuePrefix) { 388 return !strings.Contains(categories, constant.RemoveValuePrefix+category) 389 } else { 390 return strings.Contains(categories, category) 391 } 392 } 393 394 func getSubscribedOverrideUrl(providerUrl *common.URL) *common.URL { 395 newUrl := providerUrl.Clone() 396 newUrl.Protocol = constant.ProviderProtocol 397 newUrl.SetParam(constant.CategoryKey, constant.ConfiguratorsCategory) 398 newUrl.SetParam(constant.CheckKey, "false") 399 return newUrl 400 } 401 402 // Destroy registry protocol 403 func (proto *registryProtocol) Destroy() { 404 proto.bounds.Range(func(key, value interface{}) bool { 405 // protocol holds the exporters actually, instead, registry holds them in order to avoid export repeatedly, so 406 // the work for unexport should be finished in protocol.UnExport(), see also config.destroyProviderProtocols(). 407 exporter := value.(*exporterChangeableWrapper) 408 reg := proto.getRegistry(getRegistryUrl(exporter.originInvoker)) 409 if err := reg.UnRegister(exporter.registerUrl); err != nil { 410 panic(err) 411 } 412 // TODO unsubscribeUrl 413 414 // close all protocol server after consumerUpdateWait + stepTimeout(max time wait during 415 // waitAndAcceptNewRequests procedure) 416 go func() { 417 select { 418 case <-time.After(config.GetShutDown().GetStepTimeout() + config.GetShutDown().GetConsumerUpdateWaitTime()): 419 exporter.UnExport() 420 proto.bounds.Delete(key) 421 } 422 }() 423 return true 424 }) 425 426 proto.registries.Range(func(key, value interface{}) bool { 427 proto.registries.Delete(key) 428 return true 429 }) 430 } 431 432 func getRegistryUrl(invoker protocol.Invoker) *common.URL { 433 // here add * for return a new url 434 url := invoker.GetURL() 435 // if the protocol == registry, set protocol the registry value in url.params 436 if url.Protocol == constant.RegistryProtocol { 437 url.Protocol = url.GetParam(constant.RegistryKey, "") 438 } 439 return url 440 } 441 442 func getProviderUrl(invoker protocol.Invoker) *common.URL { 443 url := invoker.GetURL() 444 // be careful params maps in url is map type 445 return url.SubURL.Clone() 446 } 447 448 func setProviderUrl(regURL *common.URL, providerURL *common.URL) { 449 regURL.SubURL = providerURL 450 } 451 452 // GetProtocol return the singleton registryProtocol 453 func GetProtocol() protocol.Protocol { 454 once.Do(func() { 455 regProtocol = newRegistryProtocol() 456 }) 457 return regProtocol 458 } 459 460 type invokerDelegate struct { 461 invoker protocol.Invoker 462 protocol.BaseInvoker 463 } 464 465 func newInvokerDelegate(invoker protocol.Invoker, url *common.URL) *invokerDelegate { 466 return &invokerDelegate{ 467 invoker: invoker, 468 BaseInvoker: *protocol.NewBaseInvoker(url), 469 } 470 } 471 472 // Invoke remote service base on URL of wrappedInvoker 473 func (ivk *invokerDelegate) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result { 474 return ivk.invoker.Invoke(ctx, invocation) 475 } 476 477 type exporterChangeableWrapper struct { 478 protocol.Exporter 479 originInvoker protocol.Invoker 480 exporter protocol.Exporter 481 registerUrl *common.URL 482 subscribeUrl *common.URL 483 } 484 485 func (e *exporterChangeableWrapper) UnExport() { 486 e.exporter.UnExport() 487 } 488 489 func (e *exporterChangeableWrapper) SetRegisterUrl(registerUrl *common.URL) { 490 e.registerUrl = registerUrl 491 } 492 493 func (e *exporterChangeableWrapper) SetSubscribeUrl(subscribeUrl *common.URL) { 494 e.subscribeUrl = subscribeUrl 495 } 496 497 func (e *exporterChangeableWrapper) GetInvoker() protocol.Invoker { 498 return e.exporter.GetInvoker() 499 } 500 501 func newExporterChangeableWrapper(originInvoker protocol.Invoker, exporter protocol.Exporter) *exporterChangeableWrapper { 502 return &exporterChangeableWrapper{ 503 originInvoker: originInvoker, 504 exporter: exporter, 505 } 506 } 507 508 type providerConfigurationListener struct { 509 registry.BaseConfigurationListener 510 overrideListeners *sync.Map 511 } 512 513 func newProviderConfigurationListener(overrideListeners *sync.Map) *providerConfigurationListener { 514 listener := &providerConfigurationListener{} 515 listener.overrideListeners = overrideListeners 516 listener.InitWith( 517 config.GetRootConfig().Application.Name+constant.ConfiguratorSuffix, 518 listener, 519 extension.GetDefaultConfiguratorFunc(), 520 ) 521 return listener 522 } 523 524 // Process notified once there's any change happens on the provider config 525 func (listener *providerConfigurationListener) Process(event *config_center.ConfigChangeEvent) { 526 listener.BaseConfigurationListener.Process(event) 527 listener.overrideListeners.Range(func(key, value interface{}) bool { 528 value.(*overrideSubscribeListener).doOverrideIfNecessary() 529 return true 530 }) 531 } 532 533 type serviceConfigurationListener struct { 534 registry.BaseConfigurationListener 535 overrideListener *overrideSubscribeListener 536 providerUrl *common.URL 537 } 538 539 func newServiceConfigurationListener(overrideListener *overrideSubscribeListener, providerUrl *common.URL) *serviceConfigurationListener { 540 listener := &serviceConfigurationListener{overrideListener: overrideListener, providerUrl: providerUrl} 541 listener.InitWith( 542 providerUrl.ColonSeparatedKey()+constant.ConfiguratorSuffix, 543 listener, 544 extension.GetDefaultConfiguratorFunc(), 545 ) 546 return listener 547 } 548 549 // Process notified once there's any change happens on the service config 550 func (listener *serviceConfigurationListener) Process(event *config_center.ConfigChangeEvent) { 551 listener.BaseConfigurationListener.Process(event) 552 listener.overrideListener.doOverrideIfNecessary() 553 }