github.com/polarismesh/polaris@v1.17.8/cache/service/router_rule_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 "fmt" 22 "sync" 23 24 apitraffic "github.com/polarismesh/specification/source/go/api/v1/traffic_manage" 25 26 types "github.com/polarismesh/polaris/cache/api" 27 "github.com/polarismesh/polaris/common/model" 28 ) 29 30 type ( 31 routingLevel int16 32 boundType int16 33 34 serviceInfo interface { 35 GetNamespace() string 36 GetService() string 37 } 38 ) 39 40 const ( 41 _ routingLevel = iota 42 level1RoutingV2 43 level2RoutingV2 44 level3RoutingV2 45 46 _ boundType = iota 47 inBound 48 outBound 49 ) 50 51 func newRouteRuleBucket() *routeRuleBucket { 52 return &routeRuleBucket{ 53 rules: make(map[string]*model.ExtendRouterConfig), 54 level1Rules: map[string]map[string]struct{}{}, 55 level2Rules: map[boundType]map[string]map[string]struct{}{ 56 inBound: {}, 57 outBound: {}, 58 }, 59 level3Rules: map[boundType]map[string]struct{}{ 60 inBound: {}, 61 outBound: {}, 62 }, 63 v1rules: map[string][]*model.ExtendRouterConfig{}, 64 v1rulesToOld: map[string]string{}, 65 } 66 } 67 68 // ServiceWithCircuitBreakerRules 与服务关系绑定的熔断规则 69 type ServiceWithRouterRules struct { 70 mutex sync.RWMutex 71 Service model.ServiceKey 72 v2Rules map[string]*model.ExtendRouterConfig 73 v1Rules *apitraffic.Routing 74 Revision string 75 } 76 77 func NewServiceWithRouterRules(svcKey model.ServiceKey) *ServiceWithRouterRules { 78 return &ServiceWithRouterRules{ 79 Service: svcKey, 80 v2Rules: make(map[string]*model.ExtendRouterConfig), 81 } 82 } 83 84 func (s *ServiceWithRouterRules) AddRouterRule(rule *model.ExtendRouterConfig) { 85 s.mutex.Lock() 86 defer s.mutex.Unlock() 87 s.v2Rules[rule.ID] = rule 88 } 89 90 func (s *ServiceWithRouterRules) DelRouterRule(id string) { 91 s.mutex.Lock() 92 defer s.mutex.Unlock() 93 delete(s.v2Rules, id) 94 } 95 96 func (s *ServiceWithRouterRules) IterateRouterRules(callback func(*model.ExtendRouterConfig)) { 97 s.mutex.RLock() 98 defer s.mutex.RUnlock() 99 for _, rule := range s.v2Rules { 100 callback(rule) 101 } 102 } 103 104 func (s *ServiceWithRouterRules) CountRouterRules() int { 105 s.mutex.RLock() 106 defer s.mutex.RUnlock() 107 return len(s.v2Rules) 108 } 109 110 func (s *ServiceWithRouterRules) Clear() { 111 s.mutex.Lock() 112 defer s.mutex.Unlock() 113 s.v2Rules = make(map[string]*model.ExtendRouterConfig) 114 s.Revision = "" 115 } 116 117 // routeRuleBucket v2 路由规则缓存 bucket 118 type routeRuleBucket struct { 119 lock sync.RWMutex 120 // rules id => routing rule 121 rules map[string]*model.ExtendRouterConfig 122 // level1Rules service(name)+namespace => 路由规则ID列表,只针对某个具体的服务有效 123 level1Rules map[string]map[string]struct{} 124 // level2Rules service(*) + namespace => 路由规则ID列表, 针对某个命名空间下所有服务都生效的路由规则 125 level2Rules map[boundType]map[string]map[string]struct{} 126 // level3Rules service(*) + namespace(*) => 路由规则ID列表, 针对所有命名空间下的所有服务都生效的规则 127 level3Rules map[boundType]map[string]struct{} 128 // v1rules service-id => []*model.ExtendRouterConfig v1 版本的规则自动转为 v2 版本的规则,用于 v2 接口的数据查看 129 v1rules map[string][]*model.ExtendRouterConfig 130 131 // fetched service cache 132 // key1: namespace, key2: service 133 routerRules map[string]map[string]*ServiceWithRouterRules 134 // key1: namespace 135 nsWildcardRules map[string]*ServiceWithRouterRules 136 // all rules are wildcard specific 137 allWildcardRules *ServiceWithRouterRules 138 139 // v1rulesToOld 转为 v2 规则id 对应的原本的 v1 规则id 信息 140 v1rulesToOld map[string]string 141 } 142 143 func (b *routeRuleBucket) getV2(id string) *model.ExtendRouterConfig { 144 b.lock.RLock() 145 defer b.lock.RUnlock() 146 147 return b.rules[id] 148 } 149 150 func (b *routeRuleBucket) saveV2(conf *model.ExtendRouterConfig) { 151 b.lock.Lock() 152 defer b.lock.Unlock() 153 154 b.rules[conf.ID] = conf 155 handler := func(bt boundType, item serviceInfo) { 156 // level1 级别 cache 处理 157 if item.GetService() != model.MatchAll && item.GetNamespace() != model.MatchAll { 158 key := buildServiceKey(item.GetNamespace(), item.GetService()) 159 if _, ok := b.level1Rules[key]; !ok { 160 b.level1Rules[key] = map[string]struct{}{} 161 } 162 163 b.level1Rules[key][conf.ID] = struct{}{} 164 return 165 } 166 // level2 级别 cache 处理 167 if item.GetService() == model.MatchAll && item.GetNamespace() != model.MatchAll { 168 if _, ok := b.level2Rules[bt][item.GetNamespace()]; !ok { 169 b.level2Rules[bt][item.GetNamespace()] = map[string]struct{}{} 170 } 171 b.level2Rules[bt][item.GetNamespace()][conf.ID] = struct{}{} 172 return 173 } 174 // level3 级别 cache 处理 175 if item.GetService() == model.MatchAll && item.GetNamespace() == model.MatchAll { 176 b.level3Rules[bt][conf.ID] = struct{}{} 177 return 178 } 179 } 180 181 if conf.GetRoutingPolicy() == apitraffic.RoutingPolicy_RulePolicy { 182 subRules := conf.RuleRouting.Rules 183 for i := range subRules { 184 sources := subRules[i].Sources 185 for i := range sources { 186 item := sources[i] 187 handler(outBound, item) 188 } 189 190 destinations := subRules[i].Destinations 191 for i := range destinations { 192 item := destinations[i] 193 handler(inBound, item) 194 } 195 } 196 } 197 } 198 199 // saveV1 保存 v1 级别的路由规则 200 func (b *routeRuleBucket) saveV1(v1rule *model.RoutingConfig, v2rules []*model.ExtendRouterConfig) { 201 b.lock.Lock() 202 defer b.lock.Unlock() 203 204 b.v1rules[v1rule.ID] = v2rules 205 206 for i := range v2rules { 207 item := v2rules[i] 208 b.v1rulesToOld[item.ID] = v1rule.ID 209 } 210 } 211 212 func (b *routeRuleBucket) convertV2Size() uint32 { 213 b.lock.RLock() 214 defer b.lock.RUnlock() 215 216 return uint32(len(b.v1rulesToOld)) 217 } 218 219 func (b *routeRuleBucket) deleteV2(id string) { 220 b.lock.Lock() 221 defer b.lock.Unlock() 222 223 rule := b.rules[id] 224 delete(b.rules, id) 225 226 if rule == nil { 227 return 228 } 229 230 if rule.GetRoutingPolicy() != apitraffic.RoutingPolicy_RulePolicy { 231 return 232 } 233 234 subRules := rule.RuleRouting.Rules 235 for i := range subRules { 236 for j := range subRules[i].GetSources() { 237 source := subRules[i].GetSources()[j] 238 service := source.GetService() 239 namespace := source.GetNamespace() 240 241 if service == model.MatchAll && namespace == model.MatchAll { 242 delete(b.level3Rules[outBound], id) 243 delete(b.level3Rules[inBound], id) 244 } 245 246 if service == model.MatchAll && namespace != model.MatchAll { 247 delete(b.level2Rules[outBound][namespace], id) 248 delete(b.level2Rules[inBound][namespace], id) 249 } 250 251 if service != model.MatchAll && namespace != model.MatchAll { 252 key := buildServiceKey(namespace, service) 253 delete(b.level1Rules[key], id) 254 } 255 } 256 } 257 } 258 259 // deleteV1 删除 v1 的路由规则 260 func (b *routeRuleBucket) deleteV1(serviceId string) { 261 b.lock.Lock() 262 defer b.lock.Unlock() 263 264 items, ok := b.v1rules[serviceId] 265 if !ok { 266 delete(b.v1rules, serviceId) 267 return 268 } 269 270 for i := range items { 271 delete(b.v1rulesToOld, items[i].ID) 272 } 273 delete(b.v1rules, serviceId) 274 } 275 276 // size Number of routing-v2 cache rules 277 func (b *routeRuleBucket) size() int { 278 b.lock.RLock() 279 defer b.lock.RUnlock() 280 281 cnt := len(b.rules) 282 for k := range b.v1rules { 283 cnt += len(b.v1rules[k]) 284 } 285 286 return cnt 287 } 288 289 // listEnableRules Inquire the routing rules of the V2 version through the service name, 290 // and perform some filtering according to the Predicate 291 func (b *routeRuleBucket) listEnableRules(service, namespace string) map[routingLevel][]*model.ExtendRouterConfig { 292 ret := make(map[routingLevel][]*model.ExtendRouterConfig) 293 tmpRecord := map[string]struct{}{} 294 295 b.lock.RLock() 296 defer b.lock.RUnlock() 297 298 predicate := func(item *model.ExtendRouterConfig) bool { 299 return item.Enable 300 } 301 302 // Query Level1 V2 version routing rules 303 key := buildServiceKey(namespace, service) 304 ids := b.level1Rules[key] 305 level1 := make([]*model.ExtendRouterConfig, 0, 4) 306 for i := range ids { 307 if v, ok := b.rules[i]; ok && predicate(v) { 308 level1 = append(level1, v) 309 tmpRecord[v.ID] = struct{}{} 310 } 311 } 312 ret[level1RoutingV2] = level1 313 314 handler := func(ids map[string]struct{}, bt boundType) []*model.ExtendRouterConfig { 315 ret := make([]*model.ExtendRouterConfig, 0, 4) 316 317 for k := range ids { 318 v := b.rules[k] 319 if v == nil { 320 continue 321 } 322 if _, ok := tmpRecord[v.ID]; ok { 323 continue 324 } 325 if !predicate(v) { 326 continue 327 } 328 ret = append(ret, v) 329 tmpRecord[v.ID] = struct{}{} 330 } 331 332 return ret 333 } 334 335 // Query Level 2 level routing-v2 rules 336 level2 := make([]*model.ExtendRouterConfig, 0, 4) 337 level2 = append(level2, handler(b.level2Rules[outBound][namespace], outBound)...) 338 level2 = append(level2, handler(b.level2Rules[inBound][namespace], inBound)...) 339 ret[level2RoutingV2] = level2 340 341 // Query Level3 level routing-v2 rules 342 level3 := make([]*model.ExtendRouterConfig, 0, 4) 343 level3 = append(level3, handler(b.level3Rules[outBound], outBound)...) 344 level3 = append(level3, handler(b.level3Rules[inBound], inBound)...) 345 ret[level3RoutingV2] = level3 346 return ret 347 } 348 349 // foreach Traversing all routing rules 350 func (b *routeRuleBucket) foreach(proc types.RouterRuleIterProc) { 351 b.lock.RLock() 352 defer b.lock.RUnlock() 353 354 for k, v := range b.rules { 355 proc(k, v) 356 } 357 358 for _, rules := range b.v1rules { 359 for i := range rules { 360 proc(rules[i].ID, rules[i]) 361 } 362 } 363 } 364 365 func buildServiceKey(namespace, service string) string { 366 return fmt.Sprintf("%s@@%s", namespace, service) 367 }