英文:
How can I dynamically increase a rate limiters limit?
问题
我正在使用golang.org/x/time/rate
来限制API请求的速率。
lim := rate.NewLimiter(rateLimit, burstLimit)
for range time.NewTicker(time.Second).C {
fmt.Println(time.Now(), "tick")
go func() {
res := lim.Reserve()
if res.OK() && res.Delay() == 0 {
fmt.Println(time.Now(), "done")
} else {
fmt.Println(time.Now(), "dropped")
res.Cancel()
}
}()
}
对于可以立即执行的允许请求,有时可能需要重试该请求。这些重试的请求不应计入速率限制。根据https://cs.opensource.google/go/x/time/+/1f47c861:rate/rate.go;l=161,使用res.Cancel()
在这种情况下不会将保留的令牌返回到池中。
如何取消保留的令牌或调整限制器的状态?
英文:
I'm using golang.org/x/time/rate
for rate limiting api requests.
lim := rate.NewLimiter(rateLimit, burstLimit)
for range time.NewTicker(time.Second).C {
fmt.Println(time.Now(), "tick")
go func() {
res := lim.Reserve()
if res.OK() && res.Delay() == 0 {
fmt.Println(time.Now(), "done")
} else {
fmt.Println(time.Now(), "dropped")
res.Cancel()
}
}()
}
For allowed requests that can execute immediately, it may sometimes be necessary to retry the request. Those retried requests should not count against the rate limit. Using res.Cancel()
in that case does not return the reserved token to the pool due to https://cs.opensource.google/go/x/time/+/1f47c861:rate/rate.go;l=161.
How can reserved tokens be unreserved or the limiter's status adjusted?
答案1
得分: 2
感觉这种方法非常不正规,但似乎可以使用ReserveN
或AllowN
来使用负值将令牌返回到池中:https://play.golang.org/p/yt0RS3MJOpi
lim := rate.NewLimiter(rate.Every(3*time.Second), 1)
for range time.NewTicker(time.Second).C {
fmt.Println(time.Now(), "tick --")
go func() {
if lim.Allow() {
fmt.Println(time.Now(), "allow")
time.Sleep(time.Duration(rand.Intn(20)) * time.Millisecond)
if rand.Intn(2) == 0 {
lim.AllowN(time.Now(), -1)
fmt.Println(time.Now(), "revert")
}
} else {
fmt.Println(time.Now(), "drop")
}
}()
}
该示例显示,每当允许的操作被还原时,下一个操作也会被允许。
英文:
It feels horribly hacky, but it seems one can use ReserveN
or AllowN
with negative values to return tokens to the pool: https://play.golang.org/p/yt0RS3MJOpi
lim := rate.NewLimiter(rate.Every(3*time.Second), 1)
for range time.NewTicker(time.Second).C {
fmt.Println(time.Now(), "tick --")
go func() {
if lim.Allow() {
fmt.Println(time.Now(), "allow")
time.Sleep(time.Duration(rand.Intn(20)) * time.Millisecond)
if rand.Intn(2) == 0 {
lim.AllowN(time.Now(), -1)
fmt.Println(time.Now(), "revert")
}
} else {
fmt.Println(time.Now(), "drop")
}
}()
}
The example shows that whenever an allowed operation is reverted, the next one is allowed too.
答案2
得分: 1
你想要使用rate.Reservation.Cancel()
函数,它会尽力“撤销”一个预订,并考虑到速率限制器的并发使用。
根据文档:
Cancel
是CancelAt(time.Now())
的简写。
CancelAt
表示预订持有者不会执行预订的操作,并且会尽可能地撤销此预订对速率限制的影响,考虑到其他可能已经进行的预订。
英文:
You want rate.Reservation.Cancel() - which does a best effort at "undoing" a reservation - considering the concurrent usage of a rate-limiter.
From the docs:
> Cancel is shorthand for CancelAt(time.Now()).
>
> CancelAt indicates that the reservation holder will not perform the
> reserved action and reverses the effects of this Reservation on the
> rate limit as much as possible, considering that other reservations
> may have already been made.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论