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 }