漏桶算法
一个固定容量的漏桶,按照常量固定速率流出水滴;
如果桶是空的,则不需流出水滴;
可以以任意速率流入水滴到漏桶;
如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。
令牌桶算法
令牌将按照固定的速率被放入令牌桶中。比如每秒放10个。
桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。
当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。
如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。
漏桶和令牌桶的比较
令牌桶可以在运行时控制和调整数据处理的速率,处理某时的突发流量。放令牌的频率增加可以提升整体数据处理的速度,而通过每次获取令牌的个数增加或者放慢令牌的发放速度和降低整体数据处理速度。而漏桶不行,因为它的流出速率是固定的,程序处理速度也是固定的。
限流算法实现:
在这里我们使用Google开源项目Guava来实现限流,RateLimiter使用的是一种叫令牌桶的流控算法,RateLimiter会按照一定的频率往桶里扔令牌,线程拿到令牌才能执行。具体我们可以参考Guava的官方文档:
http://ifeve.com/guava-ratelimiter/
下面是具体的实现方法:我们模拟并发处理请求
public class MyRateLimiter { //速率是每秒10个许可 final static RateLimiter rateLimiter=RateLimiter.create(10); static Random random=new Random(); public static void main(String[] args){ final CountDownLatch countDownLatch=new CountDownLatch(1); for (int i=0;i<100;i++) { new Thread( new Runnable(){ @Override public void run() { try { //线程等待 模拟并发 countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } try { limiter(); } catch (InterruptedException e) { e.printStackTrace(); } } } ).start(); } countDownLatch.countDown(); } public static void limiter() throws InterruptedException { //采用tryAcquire()需要添加睡眠时间才能有效的看出结果 long l=random.nextInt(1000); Thread.sleep(l); if(rateLimiter.tryAcquire()){ System.out.println("正常处理....."); }else{ System.out.println("出现异常了"); } //这是线程阻塞的 返回值是double 如果返回0是有令牌的,没有令牌返回等待获取令牌的时间 /* rateLimiter.acquire(); long start = System.currentTimeMillis(); System.out.println("开始时间:"+start); System.out.println("正常处理");*/ } }
本文暂时没有评论,来添加一个吧(●'◡'●)