github.com/polarismesh/polaris@v1.17.8/cache/service/ratelimit_bucket.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package service 19 20 import ( 21 "crypto/sha1" 22 "encoding/hex" 23 "sort" 24 "sync" 25 26 "go.uber.org/zap" 27 28 types "github.com/polarismesh/polaris/cache/api" 29 "github.com/polarismesh/polaris/common/model" 30 "github.com/polarismesh/polaris/common/utils" 31 ) 32 33 func newRateLimitRuleBucket() *rateLimitRuleBucket { 34 return &rateLimitRuleBucket{ 35 ids: utils.NewSyncMap[string, *model.RateLimit](), 36 rules: utils.NewSyncMap[string, *subRateLimitRuleBucket](), 37 } 38 } 39 40 type rateLimitRuleBucket struct { 41 ids *utils.SyncMap[string, *model.RateLimit] 42 rules *utils.SyncMap[string, *subRateLimitRuleBucket] 43 } 44 45 func (r *rateLimitRuleBucket) foreach(proc types.RateLimitIterProc) { 46 r.rules.Range(func(key string, val *subRateLimitRuleBucket) bool { 47 val.foreach(proc) 48 return true 49 }) 50 } 51 52 func (r *rateLimitRuleBucket) count() int { 53 count := 0 54 r.rules.Range(func(key string, val *subRateLimitRuleBucket) bool { 55 count += val.count() 56 return true 57 }) 58 return count 59 } 60 61 func (r *rateLimitRuleBucket) saveRule(rule *model.RateLimit) { 62 r.cleanOldSvcRule(rule) 63 64 r.ids.Store(rule.ID, rule) 65 key := buildServiceKey(rule.Proto.GetNamespace().GetValue(), rule.Proto.GetService().GetValue()) 66 67 if _, ok := r.rules.Load(key); !ok { 68 r.rules.Store(key, &subRateLimitRuleBucket{ 69 rules: map[string]*model.RateLimit{}, 70 }) 71 } 72 73 b, _ := r.rules.Load(key) 74 b.saveRule(rule) 75 } 76 77 // cleanOldSvcRule 清理规则之前绑定的服务数据信息 78 func (r *rateLimitRuleBucket) cleanOldSvcRule(rule *model.RateLimit) { 79 oldRule, ok := r.ids.Load(rule.ID) 80 if !ok { 81 return 82 } 83 // 清理原来老记录的绑定数据信息 84 key := buildServiceKey(oldRule.Proto.GetNamespace().GetValue(), oldRule.Proto.GetService().GetValue()) 85 bucket, ok := r.rules.Load(key) 86 if !ok { 87 return 88 } 89 // 删除服务绑定的限流规则信息 90 bucket.delRule(rule) 91 if bucket.count() == 0 { 92 r.rules.Delete(key) 93 } 94 } 95 96 func (r *rateLimitRuleBucket) delRule(rule *model.RateLimit) { 97 r.cleanOldSvcRule(rule) 98 r.ids.Delete(rule.ID) 99 100 key := buildServiceKey(rule.Proto.GetNamespace().GetValue(), rule.Proto.GetService().GetValue()) 101 if _, ok := r.rules.Load(key); !ok { 102 return 103 } 104 105 b, _ := r.rules.Load(key) 106 b.delRule(rule) 107 if b.count() == 0 { 108 r.rules.Delete(key) 109 } 110 } 111 112 func (r *rateLimitRuleBucket) getRuleByID(id string) *model.RateLimit { 113 ret, _ := r.ids.Load(id) 114 return ret 115 } 116 117 func (r *rateLimitRuleBucket) getRules(serviceKey model.ServiceKey) ([]*model.RateLimit, string) { 118 key := buildServiceKey(serviceKey.Namespace, serviceKey.Name) 119 if _, ok := r.rules.Load(key); !ok { 120 return nil, "" 121 } 122 123 b, _ := r.rules.Load(key) 124 return b.toSlice(), b.revision 125 } 126 127 func (r *rateLimitRuleBucket) reloadRevision(serviceKey model.ServiceKey) { 128 key := buildServiceKey(serviceKey.Namespace, serviceKey.Name) 129 v, ok := r.rules.Load(key) 130 if !ok { 131 return 132 } 133 v.reloadRevision() 134 } 135 136 type subRateLimitRuleBucket struct { 137 lock sync.RWMutex 138 revision string 139 rules map[string]*model.RateLimit 140 } 141 142 func (r *subRateLimitRuleBucket) saveRule(rule *model.RateLimit) { 143 r.lock.Lock() 144 defer r.lock.Unlock() 145 146 r.rules[rule.ID] = rule 147 } 148 149 func (r *subRateLimitRuleBucket) delRule(rule *model.RateLimit) { 150 r.lock.Lock() 151 defer r.lock.Unlock() 152 153 delete(r.rules, rule.ID) 154 } 155 156 func (r *subRateLimitRuleBucket) foreach(proc types.RateLimitIterProc) { 157 r.lock.RLock() 158 defer r.lock.RUnlock() 159 160 for _, v := range r.rules { 161 proc(v) 162 } 163 } 164 165 func (r *subRateLimitRuleBucket) toSlice() []*model.RateLimit { 166 r.lock.RLock() 167 defer r.lock.RUnlock() 168 169 ret := make([]*model.RateLimit, 0, len(r.rules)) 170 for i := range r.rules { 171 ret = append(ret, r.rules[i]) 172 } 173 return ret 174 } 175 176 func (r *subRateLimitRuleBucket) count() int { 177 r.lock.RLock() 178 defer r.lock.RUnlock() 179 180 return len(r.rules) 181 } 182 183 func (r *subRateLimitRuleBucket) reloadRevision() { 184 r.lock.Lock() 185 defer r.lock.Unlock() 186 187 revisions := make([]string, 0, len(r.rules)) 188 for i := range r.rules { 189 revisions = append(revisions, r.rules[i].Revision) 190 } 191 192 sort.Strings(revisions) 193 h := sha1.New() 194 for i := range revisions { 195 if _, err := h.Write([]byte(revisions[i])); err != nil { 196 log.Error("[Cache][RateLimit] rebuild ratelimit rule revision", zap.Error(err)) 197 return 198 } 199 } 200 201 r.revision = hex.EncodeToString(h.Sum(nil)) 202 }