"golang.org/x/time/rate"
golang 提供上述包 用來對速度進行限制
Limter限制時間的發生頻率,采用令牌池的算法實現。這個池子一開始容量為b,裝滿b個令牌,然后每秒往里面填充r個令牌。
由於令牌池中最多有b個令牌,所以一次最多只能允許b個事件發生
Limter提供三中主要的函數 Allow, Reserve, and Wait. 大部分時候使用Wait。
首先創建一個rate.Limiter,其有兩個參數,第一個參數為每秒發生多少次事件,第二個參數是其緩存最大可存多少個事件。
//例如: 每秒產生200*cpu個數個令牌,最多存儲200*cpu個數個令牌。 limiter = rate.NewLimiter(rate.Limit(200.NumCPU()), 200*runtime.NumCPU())
rate.Limiter提供了三類方法用來限速
- Wait/WaitN 當沒有可用或足夠的事件時,將阻塞等待 推薦實際程序中使用這個方法
- Allow/AllowN 當沒有可用或足夠的事件時,返回false
- Reserve/ReserveN 當沒有可用或足夠的事件時,返回 Reservation,和要等待多久才能獲得足夠的事件。
Allow
func (lim *Limiter) Allow() bool //Allow 是函數 AllowN(time.Now(), 1)的簡化函數。 func (lim *Limiter) AllowN(now time.Time, n int) bool //AllowN標識在時間now的時候,n個事件是否可以同時發生(也意思就是now的時候是否可以從令牌池中取n個令牌)。如果你需要在事件超出頻率的時候丟棄或跳過事件,就使用AllowN,否則使用Reserve或Wait.
Reserve
func (lim *Limiter) Reserve() *Reservation //Reserve是ReserveN(time.Now(), 1).的簡化形式。 func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation //ReserveN 返回對象Reservation ,標識調用者需要等多久才能等到n個事件發生(意思就是等多久令牌池中至少含有n個令牌)。 //如果ReserveN 傳入的n大於令牌池的容量b,那么返回false.
使用樣例如下:
r := lim.ReserveN(time.Now(), 1) if !r.OK() { // Not allowed to act! Did you remember to set lim.burst to be > 0 ?我只要1個事件發生仍然返回false,是不是b設置為了0? return } time.Sleep(r.Delay()) Act()
如果希望根據頻率限制等待和降低事件發生的速度而不丟掉事件,就使用這個方法。
我認為這里要表達的意思就是如果事件發生的頻率是可以由調用者控制的話,可以用ReserveN 來控制事件發生的速度而不丟掉事件。如果要使用context的截止日期或cancel方法的話,使用WaitN。
Wait
//Wait是WaitN(ctx, 1)的簡化形式。 func (lim *Limiter) Wait(ctx context.Context) (err error) func (lim *Limiter) WaitN(ctx context.Context, n int) (err error) //WaitN 阻塞當前直到lim允許n個事件的發生。 //- 如果n超過了令牌池的容量大小則報錯。 //- 如果Context被取消了則報錯。 //- 如果lim的等待時間超過了Context的超時時間則報錯。
