renamed outdated rate limit struct name and added reminder to reavulate the algorithm
This commit is contained in:
parent
91f1ca273d
commit
6500b8c518
|
|
@ -234,12 +234,12 @@ func newRateLimiter(maxAllowed int, intervalInSec int64, minDeleteIntervalInSec
|
||||||
maxAllowed: maxAllowed,
|
maxAllowed: maxAllowed,
|
||||||
interval: intervalInSec,
|
interval: intervalInSec,
|
||||||
minDeleteInterval: minDeleteIntervalInSec,
|
minDeleteInterval: minDeleteIntervalInSec,
|
||||||
clients: map[string]*fixedWindow{},
|
clients: map[string]*rateClient{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type rateLimiter struct {
|
type rateLimiter struct {
|
||||||
clients map[string]*fixedWindow
|
clients map[string]*rateClient
|
||||||
|
|
||||||
maxAllowed int
|
maxAllowed int
|
||||||
interval int64
|
interval int64
|
||||||
|
|
@ -250,7 +250,7 @@ type rateLimiter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:unused
|
//nolint:unused
|
||||||
func (rt *rateLimiter) getClient(key string) (*fixedWindow, bool) {
|
func (rt *rateLimiter) getClient(key string) (*rateClient, bool) {
|
||||||
rt.RLock()
|
rt.RLock()
|
||||||
client, ok := rt.clients[key]
|
client, ok := rt.clients[key]
|
||||||
rt.RUnlock()
|
rt.RUnlock()
|
||||||
|
|
@ -269,7 +269,7 @@ func (rt *rateLimiter) isAllowed(key string) bool {
|
||||||
// check again in case the client was added by another request
|
// check again in case the client was added by another request
|
||||||
client, ok = rt.clients[key]
|
client, ok = rt.clients[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
client = newFixedWindow(rt.maxAllowed, rt.interval)
|
client = newRateClient(rt.maxAllowed, rt.interval)
|
||||||
rt.clients[key] = client
|
rt.clients[key] = client
|
||||||
}
|
}
|
||||||
rt.Unlock()
|
rt.Unlock()
|
||||||
|
|
@ -295,7 +295,7 @@ func (rt *rateLimiter) clean() {
|
||||||
//
|
//
|
||||||
// @todo remove after https://github.com/golang/go/issues/20135
|
// @todo remove after https://github.com/golang/go/issues/20135
|
||||||
if rt.totalDeleted >= 300 {
|
if rt.totalDeleted >= 300 {
|
||||||
shrunk := make(map[string]*fixedWindow, len(rt.clients))
|
shrunk := make(map[string]*rateClient, len(rt.clients))
|
||||||
for k, v := range rt.clients {
|
for k, v := range rt.clients {
|
||||||
shrunk[k] = v
|
shrunk[k] = v
|
||||||
}
|
}
|
||||||
|
|
@ -304,14 +304,20 @@ func (rt *rateLimiter) clean() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFixedWindow(maxAllowed int, intervalInSec int64) *fixedWindow {
|
func newRateClient(maxAllowed int, intervalInSec int64) *rateClient {
|
||||||
return &fixedWindow{
|
return &rateClient{
|
||||||
maxAllowed: maxAllowed,
|
maxAllowed: maxAllowed,
|
||||||
interval: intervalInSec,
|
interval: intervalInSec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type fixedWindow struct {
|
// @todo evaluate swiching to a more traditional fixed window or sliding window counter
|
||||||
|
// implementations since some users complained that it is not intuitive (see #7329).
|
||||||
|
//
|
||||||
|
// rateClient is a mixture of token bucket and fixed window rate limit strategies
|
||||||
|
// that refills the allowance only after at least "interval" seconds
|
||||||
|
// has elapsed since the last request.
|
||||||
|
type rateClient struct {
|
||||||
// use plain Mutex instead of RWMutex since the operations are expected
|
// use plain Mutex instead of RWMutex since the operations are expected
|
||||||
// to be mostly writes (e.g. consume()) and it should perform better
|
// to be mostly writes (e.g. consume()) and it should perform better
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
@ -324,18 +330,18 @@ type fixedWindow struct {
|
||||||
|
|
||||||
// hasExpired checks whether it has been at least minElapsed seconds since the lastConsume time.
|
// hasExpired checks whether it has been at least minElapsed seconds since the lastConsume time.
|
||||||
// (usually used to perform periodic cleanup of staled instances).
|
// (usually used to perform periodic cleanup of staled instances).
|
||||||
func (l *fixedWindow) hasExpired(relativeNow int64, minElapsed int64) bool {
|
func (l *rateClient) hasExpired(relativeNow int64, minElapsed int64) bool {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
|
|
||||||
return relativeNow-l.lastConsume > minElapsed
|
return relativeNow-l.lastConsume > minElapsed
|
||||||
}
|
}
|
||||||
|
|
||||||
// consume decrease the current window allowance with 1 (if not exhausted already).
|
// consume decreases the current allowance with 1 (if not exhausted already).
|
||||||
//
|
//
|
||||||
// It returns false if the allowance has been already exhausted and the user
|
// It returns false if the allowance has been already exhausted and the user
|
||||||
// has to wait until it resets back to its maxAllowed value.
|
// has to wait until it resets back to its maxAllowed value.
|
||||||
func (l *fixedWindow) consume() bool {
|
func (l *rateClient) consume() bool {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue