[Go]GO實現滑動窗口限流算法-單機版


本代碼基於原博客java版本的GO實現 , 原文解釋也比較詳細 , 這里也放上原文鏈接:https://www.cnblogs.com/dijia478/p/13807826.html

具體解釋如下 , 代碼在最下面

1.10秒內通過5次 , 這條線就是隊列list,當第一個事件進來,隊列大小是0,時間是第1秒:

 

 2.因為size=0,小於5,都沒有到限制的次數,完全不用考慮時間窗口,直接把這次事件的時間戳放到0的位置:

 

3.第2.8秒的時候,第二個事件來了。因為此時size=1,還是小於5,把這次事件的時間戳放到0的位置,原來第1秒來的事件時間戳會往后移動一格:

 

4.陸續的又來了3個事件,隊列大小變成了5,先來的時間戳依次向后移動。此時,第6個事件來了,時間是第8秒:

 

5.因為size=5,不小於5,此時已經達到限制次數,以后都需要考慮時間窗口了。所以取出位置4的時間(離現在最遠的時間),和第6個事件的時間戳做比較:

 

6.得到的差是7秒,小於時間窗口10秒,說明在10秒內,來的事件個數大於5了,所以本次不允許通過:

 

7.接下來即便來上100個事件,只要時間差小於等於10秒,都同上,拒絕通過:

 

8.第11.1秒,第101次事件過來了。因為size=5,不小於5,所以取出位置4的時間(離現在最遠的時間),和第101個事件的時間戳做比較:

 

9.得到的差是10.1秒,大於時間窗口10秒,說明在10秒內,來的事件個數小於等於5了,所以本次允許通過:

 

10.刪除位置4的時間(離現在最遠的時間),把這次事件的時間戳放到0的位置,后面的時間戳依次向后移動:

 

往后再來其他事件,就是重復4-10的步驟,即可實現,在任意滑動時間窗口內,限制通過的次數

其本質思想是轉換概念,將原本問題的確定時間大小,進行次數限制。轉換成確定次數大小,進行時間限制。

package utils

import "time"

var LimitQueue map[string][]int64
var ok bool

//單機時間滑動窗口限流法
func LimitFreqSingle(queueName string, count uint, timeWindow int64) bool {
    currTime := time.Now().Unix()
    if LimitQueue == nil {
        LimitQueue = make(map[string][]int64)
    }
    if _, ok = LimitQueue[queueName]; !ok {
        LimitQueue[queueName] = make([]int64, 0)
    }
    //隊列未滿
    if uint(len(LimitQueue[queueName])) < count {
        LimitQueue[queueName] = append(LimitQueue[queueName], currTime)
        return true
    }
    //隊列滿了,取出最早訪問的時間
    earlyTime := LimitQueue[queueName][0]
    //說明最早期的時間還在時間窗口內,還沒過期,所以不允許通過
    if currTime-earlyTime <= timeWindow {
        return false
    } else {
        //說明最早期的訪問應該過期了,去掉最早期的
        LimitQueue[queueName] = LimitQueue[queueName][1:]
        LimitQueue[queueName] = append(LimitQueue[queueName], currTime)
    }
    return true
}

 使用的案例:

func limitIpFreq(c *gin.Context, timeWindow int64, count uint) bool {
    ip := c.ClientIP()
    key := "limit:" + ip
    if !utils.LimitFreqSingle(key, count, timeWindow) {
        c.JSON(200, gin.H{
            "code": 400,
            "msg":  "error Current IP frequently visited",
        })
        return false
    }
    return true
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM