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

huangapple go评论128阅读模式
英文:

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

感觉这种方法非常不正规,但似乎可以使用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")
			}
		}()
	}

该示例显示,每当允许的操作被还原时,下一个操作也会被允许。

英文:

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()函数,它会尽力“撤销”一个预订,并考虑到速率限制器的并发使用。

根据文档:

CancelCancelAt(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.

huangapple
  • 本文由 发表于 2021年9月21日 00:14:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/69257714.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定