我用于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()
}
}()
}
Run Code Online (Sandbox Code Playgroud)
对于允许立即执行的请求,有时可能需要重试该请求。这些重试的请求不应计入速率限制。在这种情况下使用res.Cancel()不会将保留的令牌返回到池中,因为https://cs.opensource.google/go/x/time/+/1f47c861:rate/rate.go;l=161。
如何取消保留的代币或调整限制器的状态?
感觉非常糟糕,但似乎可以使用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")
}
}()
}
Run Code Online (Sandbox Code Playgroud)
该示例表明,每当恢复允许的操作时,也允许下一个操作。
| 归档时间: |
|
| 查看次数: |
516 次 |
| 最近记录: |