Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Merge pull request #2986 from fluxcd/rate-limiter-cooldown
Browse files Browse the repository at this point in the history
Introduce cooldown period in rate limiter
  • Loading branch information
squaremo authored Jul 8, 2020
2 parents 31908ab + e92fd4f commit 896c79e
Showing 1 changed file with 22 additions and 9 deletions.
31 changes: 22 additions & 9 deletions pkg/registry/middleware/rate_limiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import (
"net/http"
"strconv"
"sync"
"time"

"github.com/go-kit/kit/log"
"github.com/pkg/errors"
"golang.org/x/time/rate"
)

const (
minLimit = 0.1
backOffBy = 2.0
recoverBy = 1.5
minLimit = 0.1
backOffBy = 2.0
recoverBy = 1.5
coolDownInSeconds = 1200
)

// RateLimiters keeps track of per-host rate limiting for an arbitrary
Expand All @@ -29,11 +31,12 @@ const (
// without incident, which will increase the rate limit modestly back
// towards the given ideal.
type RateLimiters struct {
RPS float64
Burst int
Logger log.Logger
perHost map[string]*rate.Limiter
mu sync.Mutex
RPS float64
Burst int
Logger log.Logger
perHost map[string]*rate.Limiter
latestBackOffPerHost map[string]time.Time
mu sync.Mutex
}

func (limiters *RateLimiters) clip(limit float64) float64 {
Expand Down Expand Up @@ -70,7 +73,12 @@ func (limiters *RateLimiters) backOff(host string) {
if oldLimit != newLimit && limiters.Logger != nil {
limiters.Logger.Log("info", "reducing rate limit", "host", host, "limit", strconv.FormatFloat(newLimit, 'f', 2, 64))
}
limiter.SetLimit(rate.Limit(newLimit))
backOffTime := time.Now()
limiter.SetLimitAt(backOffTime, rate.Limit(newLimit))
if limiters.latestBackOffPerHost == nil {
limiters.latestBackOffPerHost = map[string]time.Time{}
}
limiters.latestBackOffPerHost[host] = backOffTime
}

// Recover should be called when a use of a RoundTripper has
Expand All @@ -81,6 +89,11 @@ func (limiters *RateLimiters) Recover(host string) {
if limiters.perHost == nil {
return
}
if limiters.latestBackOffPerHost != nil {
if t, ok := limiters.latestBackOffPerHost[host]; ok && time.Since(t) < coolDownInSeconds*time.Second {
return
}
}
if limiter, ok := limiters.perHost[host]; ok {
oldLimit := float64(limiter.Limit())
newLimit := limiters.clip(oldLimit * recoverBy)
Expand Down

0 comments on commit 896c79e

Please sign in to comment.