dubbo.apache.org/dubbo-go/v3@v3.1.1/cluster/loadbalance/ringhash/ringhash.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 ringhash
    19  
    20  import (
    21  	"strconv"
    22  )
    23  
    24  import (
    25  	"github.com/dubbogo/gost/log/logger"
    26  )
    27  
    28  import (
    29  	"dubbo.apache.org/dubbo-go/v3/cluster/loadbalance"
    30  	"dubbo.apache.org/dubbo-go/v3/common"
    31  	"dubbo.apache.org/dubbo-go/v3/common/constant"
    32  	"dubbo.apache.org/dubbo-go/v3/common/extension"
    33  	"dubbo.apache.org/dubbo-go/v3/protocol"
    34  	"dubbo.apache.org/dubbo-go/v3/remoting/xds"
    35  )
    36  
    37  func init() {
    38  	extension.SetLoadbalance(constant.LoadXDSRingHash, newRingHashLoadBalance)
    39  }
    40  
    41  type invokerWrapper struct {
    42  	invoker protocol.Invoker
    43  	weight  int
    44  }
    45  
    46  type ringhashLoadBalance struct {
    47  	client xds.XDSWrapperClient
    48  }
    49  
    50  // newRingHashLoadBalance xds ring hash
    51  //
    52  // The same parameters of the request is always sent to the same provider.
    53  func newRingHashLoadBalance() loadbalance.LoadBalance {
    54  	return &ringhashLoadBalance{client: xds.GetXDSWrappedClient()}
    55  }
    56  
    57  // Select gets invoker based on load balancing strategy
    58  func (lb *ringhashLoadBalance) Select(invokers []protocol.Invoker, invocation protocol.Invocation) protocol.Invoker {
    59  	url := invocation.Invoker().GetURL()
    60  	serviceUniqueKey := common.GetSubscribeName(url)
    61  	hostAddr, err := lb.client.GetHostAddrByServiceUniqueKey(serviceUniqueKey)
    62  	if err != nil {
    63  		logger.Errorf("[xds ringhash] GetHostAddrByServiceUniqueKey failed,error=%v", err)
    64  		return nil
    65  	}
    66  	clusterUpdate := lb.client.GetClusterUpdateIgnoreVersion(hostAddr)
    67  	policy := clusterUpdate.LBPolicy
    68  	if policy.MaximumRingSize < policy.MinimumRingSize {
    69  		logger.Errorf("[xds ringhash] ringsize parameter is invalid. MinimumRingSize=%d,MaximumRingSize=%d", policy.MaximumRingSize, policy.MaximumRingSize)
    70  		return nil
    71  	}
    72  	invokerWrappers := make([]invokerWrapper, 0, len(invokers))
    73  	for _, v := range invokers {
    74  		weight, _ := strconv.Atoi(v.GetURL().GetParam(constant.EndPointWeight, "1"))
    75  		invokerWrappers = append(invokerWrappers, invokerWrapper{invoker: v, weight: weight})
    76  	}
    77  	ring, err := lb.generateRing(invokerWrappers, policy.MinimumRingSize, policy.MaximumRingSize)
    78  	if err != nil {
    79  		logger.Errorf("[xds ringhash] ringsize parameter is invalid. MinimumRingSize=%d,MaximumRingSize=%d", policy.MaximumRingSize, policy.MaximumRingSize)
    80  		return nil
    81  	}
    82  
    83  	routerConfig := lb.client.GetRouterConfig(hostAddr)
    84  	router, err := lb.client.MatchRoute(routerConfig, invocation)
    85  	if err != nil {
    86  		logger.Errorf("[xds ringhash] not found route,method=%s", invocation.MethodName())
    87  		return nil
    88  	}
    89  	return lb.pick(lb.generateHash(invocation, router.HashPolicies), ring).invoker
    90  }