go-rate庫-限流

go-rate

https://pkg.go.dev/github.com/beefsack/go-rate#section-sourcefiles

用法

  • new():創(chuàng)建一個實例

  • wait():用來阻塞等待

  • try():返回兩個值,一個是表示是否可以立刻執(zhí)行,另一個是需要延遲多久執(zhí)行

實現(xiàn)

它的實現(xiàn)是,任何一段時間interval內,不能有超過limit個請求

維護一個隊列,隊列頭是最早的時間,隊列元素不會刪(相當于固定的token數(shù)),到了limit后就從頭部移動到尾部

假如當前隊列中數(shù)目不超過limit個(最一開始的情況)

后面的情況就是:每次對比下隊列中最早的時間和當前時間,最早時間超過了當前時間說明已經被處理過了相當于有空閑token了,所以可以處理(設置時間,移動到隊列尾),不用sleep;否則就sleep這個差值。

// Try returns true if under the rate limit, or false if over and the
// remaining time before the rate limit expires.
func (r *RateLimiter) Try() (ok bool, remaining time.Duration) {
    r.mtx.Lock()
    defer r.mtx.Unlock()
    now := time.Now()
    if l := r.times.Len(); l < r.limit {
        r.times.PushBack(now)
        return true, 0
    }
    frnt := r.times.Front()
    if diff := now.Sub(frnt.Value.(time.Time)); diff < r.interval {
        return false, r.interval - diff
    }
    frnt.Value = now
    r.times.MoveToBack(frnt)
    return true, 0
}

關鍵的操作是:if diff := now.Sub(frnt.Value.(time.Time)); diff < r.interval

走到這里隊列是已經滿了,必須擠掉一個人,且是擠掉最老的人,frnt是隊列中最老的時間,所以當前時間和他相比,只要當前時間比最老的時間老且超過的時間小于r.interval - diff。

設計的含義是:r.interval這段時間內只能有r.limit個元素,隊列長度最大就是r.limit;隊列從頭到尾時間是越來越新(大)。所以如果來一個新的請求,隊列又滿了,那么需要這個新請求的時間比最老的時間大且要大r.interval這么久,因為超過r.interval,這個最老的請求就可以移除了

aa

其他

它的處理不是時間片均勻的, 比如說設置1s有100個token,有100個線程來搶,cpu處理很快的話,可能0.1秒就處理完了剩下0.9秒都是閑的,這樣的話CPU峰值會高但其他時間可能很閑。即CPU的工作不是很均勻。

增加分時間段不同的限流的功能

隊列長度是動態(tài)變化的,不同的時間段,隊列長度不同

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容