常用限流策略——漏桶与令牌桶介绍

115 阅读4分钟

限流

限流又称为流量控制(流控),通常是指限制到达系统的并发请求数。

限流虽然会影响部分用户的使用体验,但是能确保系统的稳定性,不至于让所有用户都无法使用。

限流的一些应用:

  1. 防止恶意攻击:通过限制来自同一IP或同一用户的请求数量,可以有效地防止恶意攻击和爬虫采集。
  2. 控制资源使用:对于一些需要付费使用的服务,可以通过限流来控制资源的消耗,避免资源浪费。
  3. 用户请求限制:每个用户在一定时间内针对某个请求只能发起有限次数的请求,以控制用户行为。

常用的限流策略

漏桶

漏桶限流策略是一种常用的流量控制算法,它通过限制单位时间内处理的请求数量来达到限流的目的。以下是漏桶限流策略的主要特点和工作原理:

  1. 基本概念:漏桶算法将请求比作水,系统比作桶。水(请求)以任意速率流入桶中,而桶以固定速率“漏”出水,即以固定速率处理请求。
  2. 固定速率:漏桶算法规定了桶的漏出速率,即系统能够处理请求的最大速率。这个速率是固定的,不随外部请求的频率变化。
  3. 桶的容量:桶的容量决定了漏桶算法能够容纳的请求数量。如果桶满了,新的请求将被拒绝或者排队等待。
  4. 请求处理:当请求到达时,如果桶中有足够的空间(即桶未满),请求被接受并放入桶中;如果桶已满,请求将被丢弃或排队。
  5. 平滑流量:漏桶算法可以平滑突发流量,因为它强制请求以固定的速率被处理,而不是按照它们到达的速率。
  6. 适用场景:漏桶算法适用于需要平滑流量的场景,例如在网络通信、API网关等场景中,它可以保护后端服务不受突发流量的影响。
  7. 缺点:漏桶算法的主要缺点是它不能处理突发流量,因为它强制所有请求以固定速率被处理,即使系统有能力在某一时刻处理更多的请求。
  8. 与其他算法的比较:与令牌桶算法相比,漏桶算法缺乏处理突发流量的能力。令牌桶算法允许在桶未满的情况下,以高于固定速率处理请求。
  9. 实现工具:许多开源框架和中间件,如Redis、Nginx等,提供了基于漏桶算法的限流功能,可以方便地集成到系统中。

令牌漏桶

令牌桶限流策略是一种流行的流量控制算法,它允许在一定时间内以一定的速率处理请求,同时也能够处理突发流量。以下是令牌桶限流策略的详细解释:

基本概念

  1. 令牌桶:一个虚拟的桶,用来存放令牌。每个令牌代表处理一个请求的能力。
  2. 令牌生成速率:令牌以固定速率生成,这个速率决定了系统能够处理请求的最大频率。
  3. 桶的容量:桶的大小限制了最多可以存放的令牌数量。当桶满了之后,新生成的令牌会被丢弃。

工作原理

  1. 令牌生成:系统以固定的速率向桶中添加令牌。
  2. 请求处理:当一个请求到达时,它会尝试从桶中取出一个令牌。如果桶中有令牌,请求会被处理,并且桶中的令牌数量减少一个。
  3. 桶满丢弃:如果桶已经满了,新生成的令牌会被丢弃,保证桶中的令牌数量不会超过桶的容量。
  4. 突发流量处理:如果桶中有足够的令牌,系统可以一次性处理多个并发请求,从而应对突发流量。
  5. 请求拒绝:如果桶中没有令牌,新到达的请求将被拒绝或排队等待,直到桶中有可用的令牌。

在Gin中使用令牌桶做限流中间件

使用的是github.com/juju/rateli…

func RatelimitMiddleware(fillInterval time.Duration, capacity int64) gin.HandlerFunc {
    bucket := ratelimit.NewBucket(fillInterval, capacity)
    return func(c *gin.Context) {
       // 如果取不到令牌就中断本次请求返回 rate limit...
       if bucket.TakeAvailable(1) < 1 {
          c.String(http.StatusOK, "rate limit...")
          c.Abort()
          return
       }
       c.Next()
    }
}