github.com/polarismesh/polaris@v1.17.8/store/boltdb/ratelimit.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 boltdb 19 20 import ( 21 "errors" 22 "reflect" 23 "sort" 24 "strconv" 25 "strings" 26 "time" 27 28 bolt "go.etcd.io/bbolt" 29 30 "github.com/polarismesh/polaris/common/model" 31 "github.com/polarismesh/polaris/common/utils" 32 "github.com/polarismesh/polaris/store" 33 ) 34 35 var _ store.RateLimitStore = (*rateLimitStore)(nil) 36 37 var ( 38 ErrBadParam = errors.New("missing some params") 39 ErrMultipleResult = errors.New("multiple ratelimit find") 40 ) 41 42 const ( 43 // rule 相关信息以及映射 44 tblRateLimitConfig string = "ratelimit_config" 45 RateLimitFieldID string = "ID" 46 RateLimitFieldServiceID string = "ServiceID" 47 RateLimitFieldClusterID string = "ClusterID" 48 RateLimitFieldEnableTime string = "EnableTime" 49 RateLimitFieldName string = "Name" 50 RateLimitFieldDisable string = "Disable" 51 RateLimitFieldMethod string = "Method" 52 RateLimitFieldLabels string = "Labels" 53 RateLimitFieldPriority string = "Priority" 54 RateLimitFieldRule string = "Rule" 55 RateLimitFieldRevision string = "Revision" 56 RateLimitFieldValid string = "Valid" 57 RateLimitFieldCreateTime string = "CreateTime" 58 RateLimitFieldModifyTime string = "ModifyTime" 59 RateConfFieldMtime string = "ModifyTime" 60 RateConfFieldServiceID string = "ServiceID" 61 RateConfFieldValid string = "Valid" 62 ) 63 64 type rateLimitStore struct { 65 handler BoltHandler 66 } 67 68 // CreateRateLimit 新增限流规则 69 func (r *rateLimitStore) CreateRateLimit(limit *model.RateLimit) error { 70 if limit.ID == "" || limit.Revision == "" { 71 log.Error("[Store][boltdb] create ratelimit missing some params") 72 return ErrBadParam 73 } 74 75 return r.createRateLimit(limit) 76 } 77 78 // UpdateRateLimit 更新限流规则 79 func (r *rateLimitStore) UpdateRateLimit(limit *model.RateLimit) error { 80 if limit.ID == "" || limit.Revision == "" { 81 log.Error("[Store][boltdb] update ratelimit missing some params") 82 return ErrBadParam 83 } 84 85 return r.updateRateLimit(limit) 86 } 87 88 // EnableRateLimit 激活限流规则 89 func (r *rateLimitStore) EnableRateLimit(limit *model.RateLimit) error { 90 if limit.ID == "" || limit.Revision == "" { 91 log.Error("[Store][boltdb] update ratelimit missing some params") 92 return ErrBadParam 93 } 94 return r.enableRateLimit(limit) 95 } 96 97 // DeleteRateLimit 删除限流规则 98 func (r *rateLimitStore) DeleteRateLimit(limit *model.RateLimit) error { 99 if limit.ID == "" || limit.Revision == "" { 100 log.Error("[Store][boltdb] delete ratelimit missing some params") 101 return ErrBadParam 102 } 103 104 return r.deleteRateLimit(limit) 105 } 106 107 // GetExtendRateLimits 根据过滤条件拉取限流规则 108 func (r *rateLimitStore) GetExtendRateLimits( 109 query map[string]string, offset uint32, limit uint32) (uint32, []*model.ExtendRateLimit, error) { 110 111 handler := r.handler 112 fields := append(utils.CollectMapKeys(query), RateConfFieldServiceID, RateConfFieldValid) 113 114 result, err := handler.LoadValuesByFilter(tblRateLimitConfig, fields, &model.RateLimit{}, 115 func(m map[string]interface{}) bool { 116 validVal, ok := m[RateConfFieldValid] 117 if ok && !validVal.(bool) { 118 return false 119 } 120 delete(m, RateConfFieldValid) 121 122 for k, v := range query { 123 if k == "name" || k == "method" || k == "labels" { 124 if !strings.Contains(m[k].(string), v) { 125 return false 126 } 127 } else if k == "disable" { 128 if v != strconv.FormatBool(m[RateLimitFieldDisable].(bool)) { 129 return false 130 } 131 } else { 132 qV := m[k] 133 if !reflect.DeepEqual(qV, v) { 134 return false 135 } 136 } 137 } 138 return true 139 }) 140 141 if err != nil { 142 return 0, nil, err 143 } 144 if len(result) == 0 { 145 return 0, []*model.ExtendRateLimit{}, nil 146 } 147 148 out := make([]*model.ExtendRateLimit, 0, len(result)) 149 for _, r := range result { 150 var temp model.ExtendRateLimit 151 temp.RateLimit = r.(*model.RateLimit) 152 153 out = append(out, &temp) 154 } 155 156 return uint32(len(result)), getRealRateConfList(out, offset, limit), nil 157 } 158 159 // GetRateLimitWithID 根据限流ID拉取限流规则 160 func (r *rateLimitStore) GetRateLimitWithID(id string) (*model.RateLimit, error) { 161 if id == "" { 162 return nil, ErrBadParam 163 } 164 165 handler := r.handler 166 result, err := handler.LoadValues(tblRateLimitConfig, []string{id}, &model.RateLimit{}) 167 168 if err != nil { 169 log.Errorf("[Store][boltdb] get rate limit fail : %s", err.Error()) 170 return nil, err 171 } 172 173 if len(result) > 1 { 174 return nil, ErrMultipleResult 175 } 176 177 if len(result) == 0 { 178 return nil, nil 179 } 180 181 rateLimitRet := result[id].(*model.RateLimit) 182 if rateLimitRet.Valid { 183 return rateLimitRet, nil 184 } 185 186 return nil, nil 187 } 188 189 // GetRateLimitsForCache 根据修改时间拉取增量限流规则及最新版本号 190 func (r *rateLimitStore) GetRateLimitsForCache(mtime time.Time, 191 firstUpdate bool) ([]*model.RateLimit, error) { 192 handler := r.handler 193 194 if firstUpdate { 195 mtime = time.Time{} 196 } 197 198 var ( 199 fields = []string{RateConfFieldMtime, RateConfFieldServiceID} 200 ) 201 limitResults, err := handler.LoadValuesByFilter(tblRateLimitConfig, fields, &model.RateLimit{}, 202 func(m map[string]interface{}) bool { 203 mt := m[RateConfFieldMtime].(time.Time) 204 isAfter := !mt.Before(mtime) 205 return isAfter 206 }) 207 208 if err != nil { 209 return nil, err 210 } 211 212 if len(limitResults) == 0 { 213 return []*model.RateLimit{}, nil 214 } 215 216 limits := make([]*model.RateLimit, 0, len(limitResults)) 217 218 for i := range limitResults { 219 rule := limitResults[i].(*model.RateLimit) 220 limits = append(limits, rule) 221 } 222 223 return limits, nil 224 } 225 226 // createRateLimit save model.RateLimit and model.RateLimitRevision 227 // 228 // @receiver r *rateLimitStore 229 // @param limit current limiting configuration data to be saved 230 // @return error 231 func (r *rateLimitStore) createRateLimit(limit *model.RateLimit) error { 232 handler := r.handler 233 tNow := time.Now() 234 limit.CreateTime = tNow 235 limit.ModifyTime = tNow 236 if !limit.Disable { 237 limit.EnableTime = tNow 238 } else { 239 limit.EnableTime = time.Unix(0, 0) 240 } 241 limit.Valid = true 242 return handler.Execute(true, func(tx *bolt.Tx) error { 243 // create ratelimit_config 244 if err := saveValue(tx, tblRateLimitConfig, limit.ID, limit); err != nil { 245 log.Errorf("[Store][RateLimit] create rate_limit(%s, %s), %+v, err: %s", 246 limit.ID, limit.ServiceID, limit, err.Error()) 247 return err 248 } 249 return nil 250 }) 251 } 252 253 // enableRateLimit 254 // 255 // @receiver r 256 // @param limit 257 // @return error 258 func (r *rateLimitStore) enableRateLimit(limit *model.RateLimit) error { 259 handler := r.handler 260 return handler.Execute(true, func(tx *bolt.Tx) error { 261 properties := make(map[string]interface{}) 262 properties[RateLimitFieldDisable] = limit.Disable 263 properties[RateLimitFieldRevision] = limit.Revision 264 properties[RateLimitFieldModifyTime] = time.Now() 265 if limit.Disable { 266 properties[RateLimitFieldEnableTime] = time.Unix(0, 0) 267 } else { 268 properties[RateLimitFieldEnableTime] = time.Now() 269 } 270 // create ratelimit_config 271 if err := updateValue(tx, tblRateLimitConfig, limit.ID, properties); err != nil { 272 log.Errorf("[Store][RateLimit] update rate_limit(%s, %s) err: %s", 273 limit.ID, limit.ServiceID, err.Error()) 274 return err 275 } 276 return nil 277 }) 278 } 279 280 // updateRateLimit 281 // 282 // @receiver r 283 // @param limit 284 // @return error 285 func (r *rateLimitStore) updateRateLimit(limit *model.RateLimit) error { 286 handler := r.handler 287 return handler.Execute(true, func(tx *bolt.Tx) error { 288 properties := make(map[string]interface{}) 289 properties[RateLimitFieldName] = limit.Name 290 properties[RateLimitFieldServiceID] = limit.ServiceID 291 properties[RateLimitFieldMethod] = limit.Method 292 properties[RateLimitFieldDisable] = limit.Disable 293 properties[RateLimitFieldLabels] = limit.Labels 294 properties[RateLimitFieldPriority] = limit.Priority 295 properties[RateLimitFieldRule] = limit.Rule 296 properties[RateLimitFieldRevision] = limit.Revision 297 properties[RateLimitFieldModifyTime] = time.Now() 298 if limit.Disable { 299 properties[RateLimitFieldEnableTime] = time.Unix(0, 0) 300 } else { 301 properties[RateLimitFieldEnableTime] = time.Now() 302 } 303 // create ratelimit_config 304 if err := updateValue(tx, tblRateLimitConfig, limit.ID, properties); err != nil { 305 log.Errorf("[Store][RateLimit] update rate_limit(%s, %s) err: %s", 306 limit.ID, limit.ServiceID, err.Error()) 307 return err 308 } 309 return nil 310 }) 311 } 312 313 // deleteRateLimit 314 // 315 // @receiver r 316 // @param limit 317 // @return error 318 func (r *rateLimitStore) deleteRateLimit(limit *model.RateLimit) error { 319 handler := r.handler 320 321 return handler.Execute(true, func(tx *bolt.Tx) error { 322 323 properties := make(map[string]interface{}) 324 properties[RateLimitFieldValid] = false 325 properties[RateLimitFieldModifyTime] = time.Now() 326 327 if err := updateValue(tx, tblRateLimitConfig, limit.ID, properties); err != nil { 328 log.Errorf("[Store][RateLimit] delete rate_limit(%s, %s) err: %s", 329 limit.ID, limit.ServiceID, err.Error()) 330 return err 331 } 332 return nil 333 }) 334 } 335 336 func getRealRateConfList(routeConf []*model.ExtendRateLimit, offset, limit uint32) []*model.ExtendRateLimit { 337 338 beginIndex := offset 339 endIndex := beginIndex + limit 340 totalCount := uint32(len(routeConf)) 341 // handle invalid offset, limit 342 if totalCount == 0 { 343 return routeConf 344 } 345 if beginIndex >= endIndex { 346 return routeConf 347 } 348 if beginIndex >= totalCount { 349 return routeConf 350 } 351 if endIndex > totalCount { 352 endIndex = totalCount 353 } 354 355 sort.Slice(routeConf, func(i, j int) bool { 356 // sort by modify time 357 if routeConf[i].RateLimit.ModifyTime.After(routeConf[j].RateLimit.ModifyTime) { 358 return true 359 } else if routeConf[i].RateLimit.ModifyTime.Before(routeConf[j].RateLimit.ModifyTime) { 360 return false 361 } else { 362 return strings.Compare(routeConf[i].RateLimit.ID, routeConf[j].RateLimit.ID) < 0 363 } 364 }) 365 366 return routeConf[beginIndex:endIndex] 367 }