RateLimiter 的限流操作---漏桶算法的应用

/**

 * @create 2021-02-15 11:35

 * @desc 请求类

 **/
public class Request
{
   private final int data;

   public Request(int data)
   {
      this.data = data;
   }

   public int getData()
   {
      return data;
   }

   @Override
   public String toString()
   {
      return "Request{" + "data=" + data + '}';
   }
}

--------------------

import com.google.common.util.concurrent.Monitor;
import com.google.common.util.concurrent.RateLimiter;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer;

import static java.lang.Thread.currentThread;

/**

 * @create 2021-02-15 11:36

 * @desc 漏桶算法的应用

 **/
public class RateLimiterBucket
{
   //漏桶采用线程安全的容器
   private  final ConcurrentLinkedQueue<Request> bucket = new ConcurrentLinkedQueue<>();
   //定义漏桶的上沿容量
   private final static int BUCKET_CAPACITY = 10;
   //定义漏桶的下沿水流速率,每秒匀速放行 5 个 Request
   private final RateLimiter rateLimiter = RateLimiter.create(5.0D);
   //提交请求时需要用到的 Monitor
   private final Monitor requestMonitor = new Monitor();
   //处理请求时需要用到的 Monitor
   private final Monitor handleMonitor = new Monitor();

   public void submitRequest(int data)
   {
      this.submitRequest(new Request(data));
   }

   // 该方法主要用于接受来自客户端提交的请求数据
   public void submitRequest(Request request)
   {

      /**
       *  enterIf() 方法: 主要用于判断当前的 Guard 是否满足临界值的判断,
       *                  也是使用比较多的一个操作,调用该方法,当前线程
       *                  并不会进入阻塞之中
       */
      if(requestMonitor.enterIf(new Monitor.Guard(requestMonitor)
       {
          @Override
          public boolean isSatisfied()
          {
             return bucket.size() < BUCKET_CAPACITY;
          }
       }))
      {
         try
         {
            // 向桶中加入新的 request
            boolean result = bucket.offer(request);
            if(result)
            {
               System.out.println(currentThread() + " submit request : " + request.getData()+
               " successfully.");
            }
            else
            {
               // 此处可以将请求数据存入“高吞吐量的 MQ 中”,然后从 MQ 中消费请求,再尝试提交
               System.out.println("produce into MQ and will try again later.");
            }
         }
         finally
         {
            requestMonitor.leave();
         }
      }
      else
      {
         // 当漏桶溢出的时候做“降权”处理
         System.out.println("The request:" + request.getData() + "will be down-dimensional handle"
               + "due to bucket is overflow");
         // 此处可以将请求数据存入“高吞吐量的 MQ 中”,然后从 MQ 中消费请求,再尝试提交
         System.out.println("produce into MQ and will try again later.");
      }
   }

   // 该方法主要从漏桶中匀速地处理相关请求
   public void handleRequest(Consumer<Request> consumer)
   {
      // 若漏桶中存在请求,则处理
      if( handleMonitor.enterIf(new Monitor.Guard(handleMonitor)
      {
         @Override
         public boolean isSatisfied()
         {
            return !bucket.isEmpty();
         }
      }))
      {
         try
         {
            // 匀速处理
            rateLimiter.acquire();
            // 处理数据
            consumer.accept(bucket.poll());
         }
         finally
         {
            handleMonitor.leave();
         }
      }
   }

}

-----------------------

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**

 * @create 2021-02-15 15:15

 * @desc 测试自定义的 RateLimiterBucket

 **/
public class Test
{
   private static final AtomicInteger data = new AtomicInteger(0);
   private static final RateLimiterBucket bucket = new RateLimiterBucket();

   public static void main(String[] args)
   {
      //启动 10 个线程模拟高并发的业务请求
      for(int i = 0 ; i < 20 ; i++)
      {
         new Thread(
               ()->
               {
                  while(true)
                  {
                     bucket.submitRequest(data.getAndIncrement());
                     try
                     {
                        TimeUnit.SECONDS.sleep(3);
                     }
                     catch (InterruptedException e)
                     {
                        e.printStackTrace();
                     }
                  }
               }
         ).start();
      }
      //启动 10 个线程模拟匀速地对漏桶中的请求进行处理
      for(int i = 0 ; i < 10 ; i++)
      {
         new Thread(
               ()->
               {
                  while(true)
                  {
                     bucket.handleRequest(System.out::println);
                  }
               }
         ).start();
      }
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小达人Fighting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值