Open ianzhang1988 opened 9 months ago
cc @Sajmani maybe?
it does appear that by passing a time before a lock is obtained to reserveN
that drift can be an issue (so setting t = time.Now()
in reserveN
results in an accurate limit).
related #23145 ?
Is there any update on this?
I think the fix is simple as below.
func (lim *Limiter) advance(t time.Time) (newT time.Time, newTokens float64) {
last := lim.last
if t.Before(last) {
// last = t
t = last // here
}
// Calculate the new number of tokens, due to time that passed.
elapsed := t.Sub(last)
delta := lim.limit.tokensFromDuration(elapsed)
tokens := lim.tokens + delta
if burst := float64(lim.burst); tokens > burst {
tokens = burst
}
return t, tokens
}
if t
is in the past, advance
should not produce any token. In the sense that token for this t
is already produced in last call of advance
.
Go version
go version go1.18.5 linux/amd64
Output of
go env
in your module/workspace:What did you do?
Here is my code
limit is set to 200k, but actually is 300k on my machine.
here is what i think is going wrong in rate.go: sometimes
lim.advance(t)
would return a time t which is in the past, then update tolim.last
and causing problem. (see// !!!
comment in code below)What did you see happen?
limiter can't limit properly in multiple goroutine
What did you expect to see?
limiter limit properly in multiple goroutine