go語言網絡編程token bucket算法實現

bucket token 令牌桶算法是網絡流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一種算法。

go語言網絡編程token bucket算法實現

首先我們有一個bucket,裡面存放了n個token,每次當有一個網絡請求時,我們發一個token,當這個請求結束時,我們再將其token收回放入bucket中。這樣我們的請求數量就不會同時超過桶內的token的數量。

可能有人想,我們創建一個數組來維護這個token也可以實現吧。但是在go語言中,我們對於每一個請求都是在一個單獨的協程中處理的,所以當有併發時,這個數組就不好維護了。當然,我們可以加鎖,但是可想而知,這個系統的性能必然下降。而且在go語言中,我們提倡的是使用channel來處理併發,所以我們將這個算法使用channel來處理是很理想的。也就是通過共享通道而不是用共享內存來解決。

今天我們先實現一個總的連接數量的限制的簡單實現:

package main
import "fmt"
type Limiter struct {
cont int
bucket chan int
}
func NewConnLimiter(cc int) *Limiter {
return &Limiter{
cont: cc,
bucket: make(chan int, cc), // buffer channel
}
}
func (cl *Limiter) GetToken(id int) bool {
if len(cl.bucket) >= cl.cont {
fmt.Println("超過限制")
return false

}
cl.bucket return true
}
func (cl *Limiter) ReleaseToken() {
c := fmt.Println(c)
}
func main() {
c := NewConnLimiter(5)
r := c.GetToken(1)
fmt.Println("獲取token結果:", r)
for i := 0; i < 5; i++ {
r := c.GetToken(i)
fmt.Println("獲取token結果:", r)
}
c.ReleaseToken()
}

這個代碼是非常簡單的,目的就是,在有一個連接時,我們就給他一個token,當他結束時,在釋放這個token。我們看一下上面代碼的運行結果:

go語言網絡編程token bucket算法實現

運行結果

我們可以看到,開始時我們設置桶的數量為5,也就是最多有5個請求可以連接,當有一個token被釋放之後,又可以有新的連接了。但是現在這個代碼有一個缺點,就是總的連接數是固定的,有時我們需要的是在一段時間內,請求數量不能超過最大的值,這是我們就需要設置一個timer,在這段時間內,我們來判斷token的數量,而且超過時間我們自動釋放token就可以了。這個代碼不再這裡演示了,希望感興趣的同學回去手動試一下,學習語言最好的方法就是動手。我之前也說過,我這裡寫的都是簡單的實現,如果大家項目中有用到,就需要隨機應變,但是基本思路都是類似的。活學活用很主要。

後續會有更多的模式和算法以及區塊鏈相關的,如果你是想學習go語言或者是對設計模式或者算法感興趣亦或是區塊鏈開發工作者,都可以關注一下。(微信公眾號:Go語言之美,更多go語言知識信息等)。公眾號會持續為大家分享更多幹貨。


分享到:


相關文章: