Add period for rate limiter middleware
This commit is contained in:
parent
377c219fd9
commit
6f4aefffe7
12 changed files with 197 additions and 21 deletions
|
@ -29,7 +29,7 @@ type rateLimiter struct {
|
|||
rate rate.Limit // reqs/s
|
||||
burst int64
|
||||
// maxDelay is the maximum duration we're willing to wait for a bucket reservation to become effective, in nanoseconds.
|
||||
// For now it is somewhat arbitrarily set to 1/rate.
|
||||
// For now it is somewhat arbitrarily set to 1/(2*rate).
|
||||
maxDelay time.Duration
|
||||
sourceMatcher utils.SourceExtractor
|
||||
next http.Handler
|
||||
|
@ -61,20 +61,34 @@ func New(ctx context.Context, next http.Handler, config dynamic.RateLimit, name
|
|||
}
|
||||
|
||||
burst := config.Burst
|
||||
if burst <= 0 {
|
||||
if burst < 1 {
|
||||
burst = 1
|
||||
}
|
||||
|
||||
// Logically, we should set maxDelay to ~infinity when config.Average == 0 (because it means to rate limiting),
|
||||
period := time.Duration(config.Period)
|
||||
if period == 0 {
|
||||
period = time.Second
|
||||
}
|
||||
|
||||
// Logically, we should set maxDelay to infinity when config.Average == 0 (because it means no rate limiting),
|
||||
// but since the reservation will give us a delay = 0 anyway in this case, we're good even with any maxDelay >= 0.
|
||||
var maxDelay time.Duration
|
||||
if config.Average != 0 {
|
||||
maxDelay = time.Second / time.Duration(config.Average*2)
|
||||
var rtl float64
|
||||
if config.Average > 0 {
|
||||
rtl = float64(config.Average*int64(time.Second)) / float64(period)
|
||||
// maxDelay does not scale well for rates below 1,
|
||||
// so we just cap it to the corresponding value, i.e. 0.5s, in order to keep the effective rate predictable.
|
||||
// One alternative would be to switch to a no-reservation mode (Allow() method) whenever we are in such a low rate regime.
|
||||
if rtl < 1 {
|
||||
maxDelay = 500 * time.Millisecond
|
||||
} else {
|
||||
maxDelay = time.Second / (time.Duration(rtl) * 2)
|
||||
}
|
||||
}
|
||||
|
||||
return &rateLimiter{
|
||||
name: name,
|
||||
rate: rate.Limit(config.Average),
|
||||
rate: rate.Limit(rtl),
|
||||
burst: burst,
|
||||
maxDelay: maxDelay,
|
||||
next: next,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue