如何动态增加速率限制器限制?

and*_*dig 5 go

我用于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

如何取消保留的代币或调整限制器的状态?

and*_*dig 2

感觉非常糟糕,但似乎可以使用ReserveNAllowN使用负值将代币返回到池中: 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)

该示例表明,每当恢复允许的操作时,也允许下一个操作。