dubbo.apache.org/dubbo-go/v3@v3.1.1/cluster/router/tag/router.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 tag
    19  
    20  import (
    21  	"strings"
    22  	"sync"
    23  )
    24  
    25  import (
    26  	"github.com/dubbogo/gost/log/logger"
    27  
    28  	"gopkg.in/yaml.v2"
    29  )
    30  
    31  import (
    32  	"dubbo.apache.org/dubbo-go/v3/common"
    33  	conf "dubbo.apache.org/dubbo-go/v3/common/config"
    34  	"dubbo.apache.org/dubbo-go/v3/common/constant"
    35  	"dubbo.apache.org/dubbo-go/v3/config"
    36  	"dubbo.apache.org/dubbo-go/v3/config_center"
    37  	"dubbo.apache.org/dubbo-go/v3/protocol"
    38  	"dubbo.apache.org/dubbo-go/v3/remoting"
    39  )
    40  
    41  type PriorityRouter struct {
    42  	routerConfigs sync.Map
    43  }
    44  
    45  func NewTagPriorityRouter() (*PriorityRouter, error) {
    46  	return &PriorityRouter{}, nil
    47  }
    48  
    49  // Route Determine the target invokers list.
    50  func (p *PriorityRouter) Route(invokers []protocol.Invoker, url *common.URL, invocation protocol.Invocation) []protocol.Invoker {
    51  	if len(invokers) == 0 {
    52  		logger.Warnf("[tag router] invokers from previous router is empty")
    53  		return invokers
    54  	}
    55  	// tag is valid in application
    56  	key := strings.Join([]string{url.GetParam(constant.ApplicationKey, ""), constant.TagRouterRuleSuffix}, "")
    57  	value, ok := p.routerConfigs.Load(key)
    58  	if !ok {
    59  		return staticTag(invokers, url, invocation)
    60  	}
    61  	routerCfg := value.(config.RouterConfig)
    62  	if !*routerCfg.Enabled || !*routerCfg.Valid {
    63  		return staticTag(invokers, url, invocation)
    64  	}
    65  	return dynamicTag(invokers, url, invocation, routerCfg)
    66  }
    67  
    68  func (p *PriorityRouter) URL() *common.URL {
    69  	return nil
    70  }
    71  
    72  func (p *PriorityRouter) Priority() int64 {
    73  	return 0
    74  }
    75  
    76  func (p *PriorityRouter) Notify(invokers []protocol.Invoker) {
    77  	if len(invokers) == 0 {
    78  		return
    79  	}
    80  	application := invokers[0].GetURL().GetParam(constant.ApplicationKey, "")
    81  	if application == "" {
    82  		logger.Error("url application is empty")
    83  		return
    84  	}
    85  	dynamicConfiguration := conf.GetEnvInstance().GetDynamicConfiguration()
    86  	if dynamicConfiguration == nil {
    87  		logger.Infof("Config center does not start, Tag router will not be enabled")
    88  		return
    89  	}
    90  	key := strings.Join([]string{application, constant.TagRouterRuleSuffix}, "")
    91  	dynamicConfiguration.AddListener(key, p)
    92  	value, err := dynamicConfiguration.GetRule(key)
    93  	if err != nil {
    94  		logger.Errorf("query router rule fail,key=%s,err=%v", key, err)
    95  		return
    96  	}
    97  	p.Process(&config_center.ConfigChangeEvent{Key: key, Value: value, ConfigType: remoting.EventTypeAdd})
    98  }
    99  
   100  func (p *PriorityRouter) Process(event *config_center.ConfigChangeEvent) {
   101  	if event.ConfigType == remoting.EventTypeDel {
   102  		p.routerConfigs.Delete(event.Key)
   103  		return
   104  	}
   105  	routerConfig, err := parseRoute(event.Value.(string))
   106  	if err != nil {
   107  		logger.Warnf("[tag router]Parse new tag route config error, %+v "+
   108  			"and we will use the original tag rule configuration.", err)
   109  		return
   110  	}
   111  	p.routerConfigs.Store(event.Key, *routerConfig)
   112  	logger.Infof("[tag router]Parse tag router config success,routerConfig=%+v", routerConfig)
   113  }
   114  
   115  func parseRoute(routeContent string) (*config.RouterConfig, error) {
   116  	routeDecoder := yaml.NewDecoder(strings.NewReader(routeContent))
   117  	routerConfig := &config.RouterConfig{}
   118  	err := routeDecoder.Decode(routerConfig)
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  	routerConfig.Valid = new(bool)
   123  	*routerConfig.Valid = true
   124  	if len(routerConfig.Tags) == 0 {
   125  		*routerConfig.Valid = false
   126  	}
   127  	return routerConfig, nil
   128  }