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()
}

这个代码是非常简单的,目的就是,在有一个手游转让连接时,我们就给他一个token,当他结束时,在释放这个token。我们看一下上面代码的运行结果:

运行结果

我们可以看到,开始时我们设置桶的数量为5,也就是最多有5个请求可以连接,当有一个token被释放之后,又可以有新的连接了。但是现在这个代码有一个缺点,就是总的连接数是固定的,有时我们需要的是在一段时间内,请求数量不能超过最大的值,这是我们就需要设置一个timer,在这段时间内,我们来判断token的数量,而且超过时间我们自动释放token就可以了。这个代码不再这里演示了,希望感兴趣的同学回去手动试一下,学习语言最好的方法就是动手。我之前也说过,我这里写的都是简单的实现,如果大家项目中有用到,就需要随机应变,但是基本思路都是类似的。活学活用很主要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值