background
Comparison of common traffic limiting algorithms
accuracy | Output jitter | Instantaneous peak flow | performance | ||
---|---|---|---|---|---|
The single window | insufficient | frequent | support | high | |
The sliding window | The more Windows, the more accurate | frequent | support | high | |
funnel | High, depending on the number of barrels | There is no | Does not support | Request queuing causes RT to increase | |
The token bucket | High, depending on the number of barrels | Supports instantaneous peak traffic, without jitter | support | high |
Golang standard library has its own implementation of the traffic limiting algorithm based on Token Bucket.
Construct
// NewLimiter returns a new Limiter that allows events up to rate r and permits
// bursts of at most b tokens.
func NewLimiter(r Limit, b int) *Limiter {
return &Limiter{
limit: r,
burst: b,
}
}
Copy the code
The standard library provides a constructor with two inputs:
- The first parameter
r Limit
Represents the number of tokens generated in the Token Bucket per second.Limit
Override of type FLOAT64. - Second parameter
b int
Is the number of tokens in the bucket in the initial state.
If we want to create a token Bucket with an initial size of 10 that then produces 5 tokens per second, we can do the following:
limiter :=rate.NewLimiter(5.10)
Copy the code
A special case
rate.Every
Time /rate provides the Every method in addition to the constructor. Such as:limiter := rate.Every(time.Second) Copy the code
Creates a token Bucket that generates one token per second.
b
= = 0
It is allowed to declare a Token Bucket with a capacity of 0, in which case all requests will be rejected.Inf
The time/rate package also declares an Inf constant, which is defined as follows:// Inf is the infinite rate limit; it allows all events (even if burst is zero). const Inf = Limit(math.MaxFloat64) Copy the code
与
b
== 0 is the opposite. By definition, if the parameterLimit
Inf will allow all requests, even ifb
= = 0.
Wait/WaitN
func (lim *Limiter) Wait(ctx context.Context) (err error)
func (lim *Limiter) WaitN(ctx context.Context, n int) (err error)
Copy the code
- Wait(CTX) is equivalent to WaitN(CTX, 1)
- If the Token Bucket does not satisfy the consumption condition (less than N), this method blocks until the condition is met or times out.
- The Wait method can be controlled by the type of context (DeadLine, TimeOut), for example.
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() err := limiter.WaitN(ctx, 2) Copy the code
Allow/AllowN
func (lim *Limiter) Allow(a) bool
func (lim *Limiter) AllowN(now time.Time, n int) bool
Copy the code
Allow(time.now ()) = AllowN(time.now (), 1)
- This method returns false if the tokens in the Token Bucket do not satisfy the consumption criteria (less than N), and true otherwise.
- In production scenarios, if the rate is too high, the request is directly lost.
Reserve/ResrveN
func (lim *Limiter) Reserve(a) *Reservation
func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation
Copy the code
Reserve(time.now ()) equivalent to ResrveN(time.now (), 1)
- The call returns one regardless of whether the consumption condition is satisfied
*Reservation
Object. - This method determines whether limit can provide N tokens at a specified time.
Reservatio.OK()
If false is returned, it indicates that the wait duration cannot be calculated and the wait duration is directly enteredCancel()
Cancel the operation and return the token used.Reservatio.OK()
If true is returned, it indicates that the token can be obtained after a period of timeDelay()
Method returns the amount of time to wait.
Dynamic Adjustment
func (lim *Limiter) SetLimit(newLimit Limit)
Copy the code
This method can dynamically change the rate at which tokens are placed