dubbo.apache.org/dubbo-go/v3@v3.1.1/xds/utils/wrr/random.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 /* 19 * 20 * Copyright 2019 gRPC authors. 21 * 22 */ 23 24 package wrr 25 26 import ( 27 "fmt" 28 "sync" 29 ) 30 31 import ( 32 "dubbo.apache.org/dubbo-go/v3/xds/utils/grpcrand" 33 ) 34 35 // weightedItem is a wrapped weighted item that is used to implement weighted random algorithm. 36 type weightedItem struct { 37 Item interface{} 38 Weight int64 39 } 40 41 func (w *weightedItem) String() string { 42 return fmt.Sprint(*w) 43 } 44 45 // randomWRR is a struct that contains weighted items implement weighted random algorithm. 46 type randomWRR struct { 47 mu sync.RWMutex 48 items []*weightedItem 49 sumOfWeights int64 50 } 51 52 // NewRandom creates a new WRR with random. 53 func NewRandom() WRR { 54 return &randomWRR{} 55 } 56 57 var grpcrandInt63n = grpcrand.Int63n 58 59 func (rw *randomWRR) Next() (item interface{}) { 60 rw.mu.RLock() 61 defer rw.mu.RUnlock() 62 if rw.sumOfWeights == 0 { 63 return nil 64 } 65 // Random number in [0, sum). 66 randomWeight := grpcrandInt63n(rw.sumOfWeights) 67 for _, item := range rw.items { 68 randomWeight = randomWeight - item.Weight 69 if randomWeight < 0 { 70 return item.Item 71 } 72 } 73 74 return rw.items[len(rw.items)-1].Item 75 } 76 77 func (rw *randomWRR) Add(item interface{}, weight int64) { 78 rw.mu.Lock() 79 defer rw.mu.Unlock() 80 rItem := &weightedItem{Item: item, Weight: weight} 81 rw.items = append(rw.items, rItem) 82 rw.sumOfWeights += weight 83 } 84 85 func (rw *randomWRR) String() string { 86 return fmt.Sprint(rw.items) 87 }