漏桶和令牌桶的限流策略

漏桶算法

go get -u go.uber.org/ratelimit
"go.uber.org/ratelimit"

我们可以简单理解为:有一个漏桶,然后不断往这个漏桶里面加水,无论加多少水,这个漏桶流出的速率是固定的,不会因为流入水的多少而改变,从而实现了水流控制,也就是限流操作。

漏桶

下面是个简单代码示例:

最重要的一个参数就是 ratelimit1.New(n),这个 n 就是两滴水流间的时间间隔。单位是纳秒

我们用下一滴水滴下落时间 - 当前 时间,如果大于0,说明还没有到达下一次水滴 滴落时间,此时还需要进行限流操作。

func rateLimit1() func(ctx *gin.Context) {
	// 生成一个限流器, 参数:两滴水滴的时间间隔
	rl := ratelimit1.New(3)
	return func(c *gin.Context) {
		if rl.Take().Sub(time.Now()) > 0 { // 检查是否需要进行限流。下一滴水滴时间 - 当前时间
			//time.Sleep(rl.Take().Sub(time.Now()))  // 需要等这么长时间 下一滴水才会滴下来
			c.String(200, "rate limit...")
			c.Abort()
			return
		}
		c.Next()
	}
}
	r.GET("/ping", rateLimit1(), pingHandler)

令牌桶算法

go get -u github.com/juju/ratelimit
"github.com/juju/ratelimit"

令牌桶算法,根据令牌桶中令牌的个数来控制请求的执行。

具体的说,令牌桶算法会不断的生成令牌并放入到令牌桶中,每个请求在执行之前,都需要从令牌桶中获取一个令牌,如果此时获取不到令牌则需要等待,直到令牌桶中有令牌为止。

请添加图片描述

下面就是一个简单代码示例:第一个参数是 令牌桶中多久填充一个新的令牌,第二个参数是 定义令牌桶的最大容量

然后创建一个令牌桶,从令牌桶中获取令牌,如果每次最少能获取一个,如果此时令牌桶里有令牌,请求可以执行,如果没有令牌,则中止当前的请求。

注意: 这里使用到了闭包,保证整个项目中只有一个令牌桶对象,并且所有的请求都共享同一个令牌桶。

func rateLimit2(fillInterval time.Duration, cap int64) func(ctx *gin.Context) {
	rl := ratelimit2.NewBucket(fillInterval, cap) // 创建了一个令牌桶
	return func(c *gin.Context) {
		//rl.Take()          // 要取几个就取几个,比如要取 两个,则数量如果小于2 直接阻塞
		// rl.TakeAvailable()  // 可以少取,比如 要取两个,如果只有一个,那就先取一个,不会阻塞
		if rl.TakeAvailable(1) == 1 { // 检查是否 至少有一个令牌可以用   括号中是要检查的令牌数量
			c.Next()
			return
		}
		c.String(200, "被限流了,请等待!!!")
		c.Abort()
	}
}
	r.GET("/hei", rateLimit2(2*time.Second, 1), heiHandler)

在这里插入图片描述

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值