go语言网络编程token bucket算法简单实现

2020-07-09 00:00:00 语言 都是 算法 请求 有一个

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


图片来源于网络

首先我们有一个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 <- id
 return true
}
func (cl *Limiter) ReleaseToken() {
 c := <-cl.bucket
 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()
}

相关文章