go语言网络编程token bucket算法简单实现
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()
}
相关文章