Documentation ¶
Overview ¶
Package rate The key observation and some code (shr) is borrowed from time/rate/rate.go
Index ¶
- type BurstLimiter
- func (lim *BurstLimiter) Allow() bool
- func (lim *BurstLimiter) AllowN(n int) bool
- func (lim *BurstLimiter) Burst() int
- func (lim *BurstLimiter) GetToken() (ok bool)
- func (lim *BurstLimiter) GetTokenN(n int) (ok bool)
- func (lim *BurstLimiter) PutToken()
- func (lim *BurstLimiter) PutTokenN(n int)
- func (lim *BurstLimiter) Reserve(ctx context.Context) *Reservation
- func (lim *BurstLimiter) ReserveN(ctx context.Context, n int) *Reservation
- func (lim *BurstLimiter) SetBurst(newBurst int)
- func (lim *BurstLimiter) Tokens() int
- func (lim *BurstLimiter) Wait(ctx context.Context) (err error)
- func (lim *BurstLimiter) WaitN(ctx context.Context, n int) (err error)
- type Reservation
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BurstLimiter ¶
type BurstLimiter struct {
// contains filtered or unexported fields
}
BurstLimiter Informally, in any large enough time interval, the BurstLimiter limits the burst tokens, with a maximum burst size of b events. As a special case, if r == Inf (the infinite rate), b is ignored. See https://en.wikipedia.org/wiki/Token_bucket for more about token buckets.
Reorder Buffer It allows instructions to be committed in-order. - Allocated by `Reserve` or `ReserveN` into account when allowing future events - Wait by `Wait` or `WaitN` blocks until lim permits n events to happen. - Complete by `PutToken` or `PutTokenN` See https://en.wikipedia.org/wiki/Re-order_buffer for more about Reorder buffer. See https://web.archive.org/web/20040724215416/http://lgjohn.okstate.edu/6253/lectures/reorder.pdf for more about Reorder buffer.
The zero value is a valid BurstLimiter, but it will reject all events. Use NewFullBurstLimiter to create non-zero Limiters.
BurstLimiter has three main methods, Allow, Reserve, and Wait. Most callers should use Wait.
Each of the three methods consumes a single token. They differ in their behavior when no token is available. If no token is available, Allow returns false. If no token is available, Reserve returns a reservation for a future token and the amount of time the caller must wait before using it. If no token is available, Wait blocks until one can be obtained or its associated context.Context is canceled.
The methods AllowN, ReserveN, and WaitN consume n tokens.
func NewEmptyBurstLimiter ¶
func NewEmptyBurstLimiter(b int) *BurstLimiter
NewEmptyBurstLimiter returns a new BurstLimiter inited with zero tokens that allows events up to burst b and permits bursts of at most b tokens.
Example ¶
package main import ( "context" "fmt" "sync" "time" "github.com/searKing/golang/go/time/rate" ) func main() { const ( burst = 3 concurrency = 2 ) limiter := rate.NewEmptyBurstLimiter(burst) ctx, cancel := context.WithTimeout(context.Background(), time.Hour) defer cancel() fmt.Printf("tokens: %d\n", limiter.Tokens()) // expect not allowed, as limiter is inited with empty tokens(0) if limiter.Allow() { fmt.Printf("allow passed\n") } else { fmt.Printf("allow refused\n") } // fill one token limiter.PutToken() fmt.Printf("tokens: %d\n", limiter.Tokens()) // expect allowed, as limiter is filled with one token(1) if limiter.Allow() { fmt.Printf("allow passed\n") } else { fmt.Printf("allow refused\n") } fmt.Printf("tokens: %d\n", limiter.Tokens()) var mu sync.Mutex var wg sync.WaitGroup for i := 0; i < concurrency; i++ { wg.Add(1) go func() { defer wg.Done() //fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339)) mu.Lock() fmt.Printf("Wait 1 Token, tokens %d\n", limiter.Tokens()) mu.Unlock() err := limiter.Wait(ctx) if err != nil { mu.Lock() fmt.Printf("err: %s\n", err.Error()) mu.Unlock() return } mu.Lock() fmt.Printf("Got 1 Token, tokens %d\n", limiter.Tokens()) mu.Unlock() }() } time.Sleep(10 * time.Millisecond) for i := 0; i < concurrency; i++ { time.Sleep(10 * time.Millisecond) mu.Lock() fmt.Printf("PutToken #%d: before tokens: %d\n", i, limiter.Tokens()) mu.Unlock() // fill one token limiter.PutToken() mu.Lock() fmt.Printf("PutToken #%d: after tokens: %d\n", i, limiter.Tokens()) mu.Unlock() } wg.Wait() fmt.Printf("tokens: %d\n", limiter.Tokens()) // expect allowed, as limiter is filled with one token(1) if limiter.Allow() { fmt.Printf("allow passed\n") } else { fmt.Printf("allow refused\n") } fmt.Printf("tokens: %d\n", limiter.Tokens()) // expect not allowed, as limiter is inited with empty tokens(0) if limiter.Allow() { fmt.Printf("allow passed\n") } else { fmt.Printf("allow refused\n") } }
Output: tokens: 0 allow refused tokens: 1 allow passed tokens: 0 Wait 1 Token, tokens 0 Wait 1 Token, tokens 0 PutToken #0: before tokens: 0 PutToken #0: after tokens: 0 Got 1 Token, tokens 0 PutToken #1: before tokens: 0 PutToken #1: after tokens: 0 Got 1 Token, tokens 0 tokens: 0 allow refused tokens: 0 allow refused
func NewFullBurstLimiter ¶
func NewFullBurstLimiter(b int) *BurstLimiter
NewFullBurstLimiter returns a new BurstLimiter inited with full tokens that allows events up to burst b and permits bursts of at most b tokens.
Example ¶
package main import ( "context" "fmt" "time" "github.com/searKing/golang/go/time/rate" ) func main() { const ( burst = 3 ) limiter := rate.NewFullBurstLimiter(burst) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() // expect dropped, as limiter is inited with full tokens(3) limiter.PutToken() for i := 0; ; i++ { //fmt.Printf("%03d %s\n", i, time.Now().Format(time.RFC3339)) fmt.Printf("Wait %03d\n", i) err := limiter.Wait(ctx) if err != nil { fmt.Printf("err: %s\n", err.Error()) return } fmt.Printf("Got %03d\n", i) if i == 0 { // refill one token limiter.PutToken() } } }
Output: Wait 000 Got 000 Wait 001 Got 001 Wait 002 Got 002 Wait 003 Got 003 Wait 004 err: context deadline exceeded
func (*BurstLimiter) Allow ¶
func (lim *BurstLimiter) Allow() bool
Allow is shorthand for AllowN(time.Now(), 1). 当没有可用或足够的事件时,返回false
func (*BurstLimiter) AllowN ¶
func (lim *BurstLimiter) AllowN(n int) bool
AllowN reports whether n events may happen at time now. Use this method if you intend to drop / skip events that exceed the rate limit. Otherwise use Reserve or Wait. 当没有可用或足够的事件时,返回false
func (*BurstLimiter) Burst ¶
func (lim *BurstLimiter) Burst() int
Burst returns the maximum burst size. Burst is the maximum number of tokens that can be consumed in a single call to Allow, Reserve, or Wait, so higher Burst values allow more events to happen at once. A zero Burst allows no events, unless limit == Inf.
func (*BurstLimiter) GetToken ¶
func (lim *BurstLimiter) GetToken() (ok bool)
GetToken is shorthand for GetTokenN(ctx, 1).
func (*BurstLimiter) GetTokenN ¶
func (lim *BurstLimiter) GetTokenN(n int) (ok bool)
GetTokenN returns true if token is got
func (*BurstLimiter) PutToken ¶
func (lim *BurstLimiter) PutToken()
PutToken is shorthand for PutTokenN(ctx, 1).
func (*BurstLimiter) PutTokenN ¶
func (lim *BurstLimiter) PutTokenN(n int)
func (*BurstLimiter) Reserve ¶
func (lim *BurstLimiter) Reserve(ctx context.Context) *Reservation
Reserve is shorthand for ReserveN(1). 当没有可用或足够的事件时,返回 Reservation,和要等待多久才能获得足够的事件。
func (*BurstLimiter) ReserveN ¶
func (lim *BurstLimiter) ReserveN(ctx context.Context, n int) *Reservation
ReserveN returns a Reservation that indicates how long the caller must wait before n events happen. The BurstLimiter takes this Reservation into account when allowing future events. ReserveN returns false if n exceeds the BurstLimiter's burst size. Usage example:
// Allocate: The dispatch stage reserves space in the reorder buffer for instructions in program order. r := lim.ReserveN(context.Background(), 1) if !r.OK() { // Not allowed to act! Did you remember to set lim.burst to be > 0 ? return } // Execute: out-of-order execution Act() // Wait: The complete stage must wait for instructions to finish execution. if err:= r.Wait();err!=nil{ // Not allowed to act! Reservation or context canceled ? return } // Complete: Finished instructions are allowed to write results in order into the architected registers. // It allows instructions to be committed in-order. defer r.PutToken() // Execute: in-order execution Act()
Use this method if you wish to wait and slow down in accordance with the rate limit without dropping events. If you need to respect a deadline or cancel the delay, use Wait instead. To drop or skip events exceeding rate limit, use Allow instead. 当没有可用或足够的事件时,返回 Reservation,和要等待多久才能获得足够的事件。 See https://en.wikipedia.org/wiki/Re-order_buffer for more about Reorder buffer. See https://web.archive.org/web/20040724215416/http://lgjohn.okstate.edu/6253/lectures/reorder.pdf for more about Reorder buffer.
func (*BurstLimiter) SetBurst ¶
func (lim *BurstLimiter) SetBurst(newBurst int)
SetBurst sets a new burst size for the limiter.
func (*BurstLimiter) Tokens ¶
func (lim *BurstLimiter) Tokens() int
Tokens returns the token nums unconsumed.
func (*BurstLimiter) Wait ¶
func (lim *BurstLimiter) Wait(ctx context.Context) (err error)
Wait is shorthand for WaitN(ctx, 1).
func (*BurstLimiter) WaitN ¶
func (lim *BurstLimiter) WaitN(ctx context.Context, n int) (err error)
WaitN blocks until lim permits n events to happen. It returns an error if n exceeds the BurstLimiter's burst size, the Context is canceled, or the expected wait time exceeds the Context's Deadline. The burst limit is ignored if the rate limit is Inf.
type Reservation ¶
type Reservation struct {
// contains filtered or unexported fields
}
A Reservation holds information about events that are permitted by a BurstLimiter to happen after a delay. A Reservation may be canceled, which may enable the BurstLimiter to permit additional events.
func (*Reservation) Cancel ¶
func (r *Reservation) Cancel()
Cancel 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.
func (*Reservation) OK ¶
func (r *Reservation) OK() bool
OK returns whether the limiter can provide the requested number of tokens within the maximum wait time. If OK is false, Delay returns InfDuration, and Cancel does nothing.