令牌桶

2018-11-23  本文已影响16人  baby_honour

对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了,令牌桶算法更为适合。令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

设置 Rate = 2 :每秒放入令牌的个数
桶的大小:100

public class TokenDemo {

  //qps:每秒钟处理完请求的次数;tps:每秒钟处理完的事务次数
  //代表qps是10;
  RateLimiter rateLimiter = RateLimiter.create(10);

  public void doSomething(){
      if (rateLimiter.tryAcquire()){//rateLimiter.acquire()
          //尝试获得令牌.为true则获取令牌成功
          System.out.println("正常处理");
      }else{
          System.out.println("处理失败");
      }

  }

  public static void main(String args[]) throws IOException{
      /*
      * CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量,此值是线程将要等待的操作数(线程的数量)。
      * 当某个线程为了想要执行这些操作而等待时, 它要使用 await()方法。
      * 此方法让线程进入休眠直到操作完成。
      * 当某个操作结束,它使用countDown() 方法来减少CountDownLatch类的内部计数器,计数器的值就会减1。
      * 当计数器到达0时,它表示所有的线程已经完成了任务,这个类会唤醒全部使用await() 方法休眠的线程们恢复执行任务。
      *
      * */
      CountDownLatch latch = new CountDownLatch(1);
      Random random = new Random(10);
      TokenDemo tokenDemo = new TokenDemo();
      for (int i=0;i<20;i++){
          new Thread(()->{
              try {
                  latch.await();
                  Thread.sleep(random.nextInt(1000));
                  tokenDemo.doSomething();
              }catch (InterruptedException e){
                  e.printStackTrace();
              }

          }).start();
      }
      latch.countDown();
      System.in.read();
  }

}

结果:

正常处理
正常处理
正常处理
正常处理
正常处理
处理失败
正常处理
处理失败
处理失败
处理失败
正常处理
处理失败
正常处理
处理失败
正常处理
正常处理
正常处理
正常处理
处理失败
处理失败

漏桶:漏桶算法能强行限制数据的传输速率。

请求先进入到漏桶里,漏桶以一定的速度出水。当水请求过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。进入端无需考虑出水端的速率,就像mq消息队列一样,provider只需要将消息传入队列中,而不需要关心Consumer是否接收到了消息。
对于溢出的水,就是被过滤的数据,可以直接被丢弃,也可以通过某种方式暂时保存,如加入队列之中,像线程池里对溢出数据的4种处理机制一样

上一篇 下一篇

猜你喜欢

热点阅读