golang.org/x/time/rate

加令牌的时机

通过初始化函数可以看到,并没有开启一个定时任务定时添加令牌,所以猜测是在每次请求令牌之前,通过时间添加固定的令牌。

func NewLimiter(r Limit, b int) *Limiter {
    return &Limiter{
        limit: r,
        burst: b,
    }
}
limitburst
advance
func (lim *Limiter) advance(now time.Time) (newNow time.Time, newLast time.Time, newTokens float64) {
    last := lim.last
    if now.Before(last) {
        last = now
    }

    // Avoid making delta overflow below when last is very old.
    maxElapsed := lim.limit.durationFromTokens(float64(lim.burst) - lim.tokens)
    elapsed := now.Sub(last)
    if elapsed > maxElapsed {
        elapsed = maxElapsed
    }

    // Calculate the new number of tokens, due to time that passed.
    delta := lim.limit.tokensFromDuration(elapsed)
    tokens := lim.tokens + delta
    if burst := float64(lim.burst); tokens > burst {
        tokens = burst
    }

    return now, last, tokens
}

两个重要的方法

AllowN
package main

import (
    "fmt"
    "time"

    "golang.org/x/time/rate"
)

func main() {
    r := rate.Every(1 * time.Second)
    limit := rate.NewLimiter(r, 10)
    for i := 0; i < 5; i++ {
        if ok := limit.AllowN(time.Now(), 3); ok {
            fmt.Println("next")
        } else {
            fmt.Println("limit")
            break
        }
    }
}
ReserveNReservation
package main

import (
    "fmt"
    "time"

    "golang.org/x/time/rate"
)

func main() {
    r := rate.Every(1 * time.Second)
    limit := rate.NewLimiter(r, 10)
    for i := 0; i < 5; i++ {
        r := limit.ReserveN(time.Now(), 8)
        fmt.Println(r.Delay())
    }
}

输出:

0s
5.999962161s
13.999959821s
21.999958261s
29.999956713s
reserveN