令牌桶算法(Token Bucket)

令牌桶算法的思想是:大小固定的令牌桶可自行以恒定的速率源源不断地产生令牌,并将产生的令牌放入桶中。如果令牌不被消耗,或者被消耗的速度小于产生的速度,令牌就会不断地增多,直到把桶填满。后面再产生的令牌就会从桶中溢出。最后桶中可以保存的最大令牌数永远不会超过桶的大小。

传送到令牌桶的数据包需要消耗令牌。不同大小的数据包,消耗的令牌数量不一样。令牌桶这种控制机制基于令牌桶中是否存在令牌来指示什么时候可以发送流量。令牌桶中的每一个令牌都代表一个字节。如果令牌桶中存在令牌,则允许发送流量;而如果令牌桶中不存在令牌,则不允许发送流量。因此,如果突发门限被合理地配置并且令牌桶中有足够的令牌,那么流量就可以以峰值速率发送。

令牌桶算法(Token Bucket)
如果想及时了解Spark、Hadoop或者Hbase相关的文章,欢迎关注微信公共帐号:iteblog_hadoop

漏桶算法和令牌桶算法的区别

漏桶算法与令牌桶算法在表面看起来类似,很容易将两者混淆。但事实上,这两者具有截然不同的特性,且为不同的目的而使用。漏桶算法与令牌桶算法的区别在于:

  • 漏桶算法能够强行限制数据的传输速率。
  • 令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发传输。
  • Guava 中的 RateLimiter

    流量限速最初来源于计算机网络,但是随着当今互联网技术的迅速发展,流量限速也被用于实际的项目工程中。比如双 11 网站限流等。

    Guava 中的 RateLimiter 就是使用上面的令牌桶算法来进行限流的,RateLimiter 会按照一定的频率往桶里扔令牌,线程拿到令牌才能执行,比如你希望自己的应用程序 QPS 不要超过 800,那么 RateLimiter 设置 800 的速率后,就会每秒往桶里扔 800 个令牌。在我们项目中使用这个也非常的简单,如下:

    package com.iteblog.www
    
    import java.util.concurrent.{Callable, Executors, TimeUnit}
    
    import com.google.common.util.concurrent.{MoreExecutors, RateLimiter}
    
    object IteblogRateLimitTest {
      class Task(index: Int) extends Callable[Integer] {
        override def call: Integer = {
          println("Execute Task - " + index)
          TimeUnit.SECONDS.sleep(1)
          0
        }
      }
    
      def main(args: Array[String]): Unit = {
        val executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool)
    
        val limiter = RateLimiter.create(2.0)
    
        (0 until 10).foreach { i =>
          limiter.acquire()
          val listenableFuture = executorService.submit(new Task(i))
        }
        executorService.shutdown()
    
      }
    }
    

    上面示例限制每秒的令牌数为2,所以可以限制每秒的 QPS 为2。limiter.acquire() 就是用于获取令牌的。

    本博客文章除特别声明,全部都是原创!
    原创文章版权归过往记忆大数据(过往记忆)所有,未经许可不得转载。
    本文链接: 【网络速率限制以及 Guava 的 RateLimiter】(https://www.iteblog.com/archives/2374.html)
    喜欢 (4)
    分享 (0)
    发表我的评论
    取消评论

    表情
    本博客评论系统带有自动识别垃圾评论功能,请写一些有意义的评论,谢谢!