sigs.k8s.io/cluster-api-provider-aws@v1.5.5/pkg/internal/rate/rate.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Package rate provides a rate limiter. 18 package rate 19 20 import ( 21 "context" 22 "fmt" 23 "math" 24 "sync" 25 "time" 26 27 "github.com/pkg/errors" 28 ) 29 30 // Limit defines the maximum frequency of some events. 31 // Limit is represented as number of events per second. 32 // A zero Limit allows no events. 33 type Limit float64 34 35 // Inf is the infinite rate limit; it allows all events (even if burst is zero). 36 const Inf = Limit(math.MaxFloat64) 37 38 // Every converts a minimum time interval between events to a Limit. 39 func Every(interval time.Duration) Limit { 40 if interval <= 0 { 41 return Inf 42 } 43 return 1 / Limit(interval.Seconds()) 44 } 45 46 // A Limiter controls how frequently events are allowed to happen. 47 // It implements a "token bucket" of size b, initially full and refilled 48 // at rate r tokens per second. 49 // Informally, in any large enough time interval, the Limiter limits the 50 // rate to r tokens per second, with a maximum burst size of b events. 51 // As a special case, if r == Inf (the infinite rate), b is ignored. 52 // See https://en.wikipedia.org/wiki/Token_bucket for more about token buckets. 53 // 54 // The zero value is a valid Limiter, but it will reject all events. 55 // Use NewLimiter to create non-zero Limiters. 56 // 57 // Limiter has three main methods, Allow, Reserve, and Wait. 58 // Most callers should use Wait. 59 // 60 // Each of the three methods consumes a single token. 61 // They differ in their behavior when no token is available. 62 // If no token is available, Allow returns false. 63 // If no token is available, Reserve returns a reservation for a future token 64 // and the amount of time the caller must wait before using it. 65 // If no token is available, Wait blocks until one can be obtained 66 // or its associated context.Context is canceled. 67 // 68 // The methods AllowN, ReserveN, and WaitN consume n tokens. 69 type Limiter struct { 70 mu sync.Mutex 71 limit Limit 72 burst int 73 tokens float64 74 // last is the last time the limiter's tokens field was updated 75 last time.Time 76 // lastEvent is the latest time of a rate-limited event (past or future) 77 lastEvent time.Time 78 } 79 80 // Limit returns the maximum overall event rate. 81 func (lim *Limiter) Limit() Limit { 82 lim.mu.Lock() 83 defer lim.mu.Unlock() 84 return lim.limit 85 } 86 87 // Burst returns the maximum burst size. Burst is the maximum number of tokens 88 // that can be consumed in a single call to Allow, Reserve, or Wait, so higher 89 // Burst values allow more events to happen at once. 90 // A zero Burst allows no events, unless limit == Inf. 91 func (lim *Limiter) Burst() int { 92 lim.mu.Lock() 93 defer lim.mu.Unlock() 94 return lim.burst 95 } 96 97 // NewLimiter returns a new Limiter that allows events up to rate r and permits 98 // bursts of at most b tokens. 99 func NewLimiter(r Limit, b int) *Limiter { 100 return &Limiter{ 101 limit: r, 102 burst: b, 103 } 104 } 105 106 // Allow is shorthand for AllowN(time.Now(), 1). 107 func (lim *Limiter) Allow() bool { 108 return lim.AllowN(time.Now(), 1) 109 } 110 111 // AllowN reports whether n events may happen at time now. 112 // Use this method if you intend to drop / skip events that exceed the rate limit. 113 // Otherwise use Reserve or Wait. 114 func (lim *Limiter) AllowN(now time.Time, n int) bool { 115 return lim.reserveN(now, n, 0).ok 116 } 117 118 // A Reservation holds information about events that are permitted by a Limiter to happen after a delay. 119 // A Reservation may be canceled, which may enable the Limiter to permit additional events. 120 type Reservation struct { 121 ok bool 122 lim *Limiter 123 tokens int 124 timeToAct time.Time 125 // This is the Limit at reservation time, it can change later. 126 limit Limit 127 } 128 129 // OK returns whether the limiter can provide the requested number of tokens 130 // within the maximum wait time. If OK is false, Delay returns InfDuration, and 131 // Cancel does nothing. 132 func (r *Reservation) OK() bool { 133 return r.ok 134 } 135 136 // Delay is shorthand for DelayFrom(time.Now()). 137 func (r *Reservation) Delay() time.Duration { 138 return r.DelayFrom(time.Now()) 139 } 140 141 // InfDuration is the duration returned by Delay when a Reservation is not OK. 142 const InfDuration = time.Duration(1<<63 - 1) 143 144 // DelayFrom returns the duration for which the reservation holder must wait 145 // before taking the reserved action. Zero duration means act immediately. 146 // InfDuration means the limiter cannot grant the tokens requested in this 147 // Reservation within the maximum wait time. 148 func (r *Reservation) DelayFrom(now time.Time) time.Duration { 149 if !r.ok { 150 return InfDuration 151 } 152 delay := r.timeToAct.Sub(now) 153 if delay < 0 { 154 return 0 155 } 156 return delay 157 } 158 159 // Cancel is shorthand for CancelAt(time.Now()). 160 func (r *Reservation) Cancel() { 161 r.CancelAt(time.Now()) 162 } 163 164 // CancelAt indicates that the reservation holder will not perform the reserved action 165 // and reverses the effects of this Reservation on the rate limit as much as possible, 166 // considering that other reservations may have already been made. 167 func (r *Reservation) CancelAt(now time.Time) { 168 if !r.ok { 169 return 170 } 171 172 r.lim.mu.Lock() 173 defer r.lim.mu.Unlock() 174 175 if r.lim.limit == Inf || r.tokens == 0 || r.timeToAct.Before(now) { 176 return 177 } 178 179 // calculate tokens to restore 180 // The duration between lim.lastEvent and r.timeToAct tells us how many tokens were reserved 181 // after r was obtained. These tokens should not be restored. 182 restoreTokens := float64(r.tokens) - r.limit.tokensFromDuration(r.lim.lastEvent.Sub(r.timeToAct)) 183 if restoreTokens <= 0 { 184 return 185 } 186 // advance time to now 187 now, _, tokens := r.lim.advance(now) 188 // calculate new number of tokens 189 tokens += restoreTokens 190 if burst := float64(r.lim.burst); tokens > burst { 191 tokens = burst 192 } 193 // update state 194 r.lim.last = now 195 r.lim.tokens = tokens 196 if r.timeToAct == r.lim.lastEvent { 197 prevEvent := r.timeToAct.Add(r.limit.durationFromTokens(float64(-r.tokens))) 198 if !prevEvent.Before(now) { 199 r.lim.lastEvent = prevEvent 200 } 201 } 202 } 203 204 // Reserve is shorthand for ReserveN(time.Now(), 1). 205 func (lim *Limiter) Reserve() *Reservation { 206 return lim.ReserveN(time.Now(), 1) 207 } 208 209 // ReserveN returns a Reservation that indicates how long the caller must wait before n events happen. 210 // The Limiter takes this Reservation into account when allowing future events. 211 // The returned Reservation’s OK() method returns false if n exceeds the Limiter's burst size. 212 // Usage example: 213 // 214 // r := lim.ReserveN(time.Now(), 1) 215 // if !r.OK() { 216 // // Not allowed to act! Did you remember to set lim.burst to be > 0 ? 217 // return 218 // } 219 // time.Sleep(r.Delay()) 220 // Act() 221 // 222 // Use this method if you wish to wait and slow down in accordance with the rate limit without dropping events. 223 // If you need to respect a deadline or cancel the delay, use Wait instead. 224 // To drop or skip events exceeding rate limit, use Allow instead. 225 func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation { 226 r := lim.reserveN(now, n, InfDuration) 227 return &r 228 } 229 230 // Wait is shorthand for WaitN(ctx, 1). 231 func (lim *Limiter) Wait(ctx context.Context) (err error) { 232 return lim.WaitN(ctx, 1) 233 } 234 235 // WaitN blocks until lim permits n events to happen. 236 // It returns an error if n exceeds the Limiter's burst size, the Context is 237 // canceled, or the expected wait time exceeds the Context's Deadline. 238 // The burst limit is ignored if the rate limit is Inf. 239 func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) { 240 lim.mu.Lock() 241 burst := lim.burst 242 limit := lim.limit 243 lim.mu.Unlock() 244 245 if n > burst && limit != Inf { 246 return errors.New(fmt.Errorf("rate: Wait(n=%d) exceeds limiter's burst %d", n, burst).Error()) 247 } 248 // Check if ctx is already cancelled 249 select { 250 case <-ctx.Done(): 251 return ctx.Err() 252 default: 253 } 254 // Determine wait limit 255 now := time.Now() 256 waitLimit := InfDuration 257 if deadline, ok := ctx.Deadline(); ok { 258 waitLimit = deadline.Sub(now) 259 } 260 // Reserve 261 r := lim.reserveN(now, n, waitLimit) 262 if !r.ok { 263 return errors.New(fmt.Errorf("rate: Wait(n=%d) would exceed context deadline", n).Error()) 264 } 265 // Wait if necessary 266 delay := r.DelayFrom(now) 267 if delay == 0 { 268 return nil 269 } 270 t := time.NewTimer(delay) 271 defer t.Stop() 272 select { 273 case <-t.C: 274 // We can proceed. 275 return nil 276 case <-ctx.Done(): 277 // Context was canceled before we could proceed. Cancel the 278 // reservation, which may permit other events to proceed sooner. 279 r.Cancel() 280 return ctx.Err() 281 } 282 } 283 284 // SetLimit is shorthand for SetLimitAt(time.Now(), newLimit). 285 func (lim *Limiter) SetLimit(newLimit Limit) { 286 lim.SetLimitAt(time.Now(), newLimit) 287 } 288 289 // SetLimitAt sets a new Limit for the limiter. The new Limit, and Burst, may be violated 290 // or underutilized by those which reserved (using Reserve or Wait) but did not yet act 291 // before SetLimitAt was called. 292 func (lim *Limiter) SetLimitAt(now time.Time, newLimit Limit) { 293 lim.mu.Lock() 294 defer lim.mu.Unlock() 295 296 now, _, tokens := lim.advance(now) 297 298 lim.last = now 299 lim.tokens = tokens 300 lim.limit = newLimit 301 } 302 303 // SetBurst is shorthand for SetBurstAt(time.Now(), newBurst). 304 func (lim *Limiter) SetBurst(newBurst int) { 305 lim.SetBurstAt(time.Now(), newBurst) 306 } 307 308 // SetBurstAt sets a new burst size for the limiter. 309 func (lim *Limiter) SetBurstAt(now time.Time, newBurst int) { 310 lim.mu.Lock() 311 defer lim.mu.Unlock() 312 313 now, _, tokens := lim.advance(now) 314 315 lim.last = now 316 lim.tokens = tokens 317 lim.burst = newBurst 318 } 319 320 // reserveN is a helper method for AllowN, ReserveN, and WaitN. 321 // maxFutureReserve specifies the maximum reservation wait duration allowed. 322 // reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN. 323 func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duration) Reservation { 324 lim.mu.Lock() 325 326 if lim.limit == Inf { 327 lim.mu.Unlock() 328 return Reservation{ 329 ok: true, 330 lim: lim, 331 tokens: n, 332 timeToAct: now, 333 } 334 } 335 336 now, last, tokens := lim.advance(now) 337 338 // Calculate the remaining number of tokens resulting from the request. 339 tokens -= float64(n) 340 341 // Calculate the wait duration 342 var waitDuration time.Duration 343 if tokens < 0 { 344 waitDuration = lim.limit.durationFromTokens(-tokens) 345 } 346 347 // Decide result 348 ok := n <= lim.burst && waitDuration <= maxFutureReserve 349 350 // Prepare reservation 351 r := Reservation{ 352 ok: ok, 353 lim: lim, 354 limit: lim.limit, 355 } 356 if ok { 357 r.tokens = n 358 r.timeToAct = now.Add(waitDuration) 359 } 360 361 // Update state 362 if ok { 363 lim.last = now 364 lim.tokens = tokens 365 lim.lastEvent = r.timeToAct 366 } else { 367 lim.last = last 368 } 369 370 lim.mu.Unlock() 371 return r 372 } 373 374 // advance calculates and returns an updated state for lim resulting from the passage of time. 375 // lim is not changed. 376 // advance requires that lim.mu is held. 377 func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time, newTokens float64) { 378 last := lim.last 379 if now.Before(last) { 380 last = now 381 } 382 383 // Avoid making delta overflow below when last is very old. 384 maxElapsed := lim.limit.durationFromTokens(float64(lim.burst) - lim.tokens) 385 elapsed := now.Sub(last) 386 if elapsed > maxElapsed { 387 elapsed = maxElapsed 388 } 389 390 // Calculate the new number of tokens, due to time that passed. 391 delta := lim.limit.tokensFromDuration(elapsed) 392 tokens := lim.tokens + delta 393 if burst := float64(lim.burst); tokens > burst { 394 tokens = burst 395 } 396 397 return now, last, tokens 398 } 399 400 // durationFromTokens is a unit conversion function from the number of tokens to the duration 401 // of time it takes to accumulate them at a rate of limit tokens per second. 402 func (limit Limit) durationFromTokens(tokens float64) time.Duration { 403 seconds := tokens / float64(limit) 404 return time.Nanosecond * time.Duration(1e9*seconds) 405 } 406 407 // tokensFromDuration is a unit conversion function from a time duration to the number of tokens 408 // which could be accumulated during that duration at a rate of limit tokens per second. 409 func (limit Limit) tokensFromDuration(d time.Duration) float64 { 410 // Split the integer and fractional parts ourself to minimize rounding errors. 411 // See golang.org/issues/34861. 412 sec := float64(d/time.Second) * float64(limit) 413 nsec := float64(d%time.Second) * float64(limit) 414 return sec + nsec/1e9 415 }