使用springmvc怎么实现一个限流拦截器

  介绍

这期内容当中小编将会给大家带来有关使用springmvc怎么实现一个限流拦截器,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

<强>限流器算法

目前常用限流器算法为两种:令牌桶算法和漏桶算法,主要区别在于:漏桶算法能够强行限制请求速率,平滑突发请求,而令牌桶算法在限定平均速率的情况下,允许一定量的突发请求

下面是从网上找到的两张算法图示,就很容易区分这两种算法的特性了

漏桶算法使用springmvc怎么实现一个限流拦截器

令牌桶算法使用springmvc怎么实现一个限流拦截器

针对接口来说,一般会允许处理一定量突发请求,只要求限制平均速率,所以令牌桶算法更加常见。

<强>令牌桶算法工具RateLimiter

目前本人常用的令牌桶算法实现类当属谷歌番石榴的RateLimiter,番石榴不仅实现了令牌桶算法,还有缓存,新的集合类,并发工具类,字符串处理类等等。是一个强大的工具集

RateLimiter api可以查看并发编程网番石榴RateLimiter的介绍

<强> RateLimiter源码分析

RateLimiter默认情况下,最核心的属性有两个nextFreeTicketMicros,下次可获取令牌时间,storedPermits桶内令牌数。

判断是否可获取令牌:

每次获取令牌的时候,根据桶内令牌数计算最快下次能获取令牌的时间nextFreeTicketMicros,判断是否可以获取资源时,只要比较nextFreeTicketMicros和当前时间就可以了,那么容易

获取令牌操作:

对于获取令牌,根据nextFreeTicketMicros和当前时间计算出新增的令牌数,写入当前令牌桶令牌数,重新计算nextFreeTicketMicros,桶内还有令牌,则写入当前时间,并减少本次请求获取的令牌数。

如同java的aq类一样,RateLimiter的核心在tryAcquire方法

, public  boolean  tryAcquire(时间允许,int  long 超时,TimeUnit 单元),{//才能尝试获取资源最多等待时间   long 才能;timeoutMicros =,马克斯(unit.toMicros(超时),0);//检才能查获取资源数目是否正确   checkPermits才能(凭许可证经营);   long 才能;microsToWait;//才能加锁   synchronized 才能;(互斥()),{   ,,//当前时间   ,,long  nowMicros =, stopwatch.readMicros ();   ,,//判断是否可以在超时时间内获取资源   ,,if  (! canAcquire (nowMicros, timeoutMicros)), {   ,,,return 假;   ,,},{else    ,,,//可获取资源,对资源进行重新计算,并返回当前线程需要休眠时间   ,,,microsToWait =, reserveAndGetWaitLength(允许,,nowMicros);   ,,}   ,,}//才能休眠   stopwatch.sleepMicrosUninterruptibly才能(microsToWait);   return 才能;真实;   以前,}

判断是否可获取令牌:

, private  boolean  canAcquire (long  nowMicros, long  timeoutMicros), {//最才能早可获取资源时间,等待时间& lt;=当前时间,方可获取资源   return 才能queryEarliestAvailable (nowMicros),安康;timeoutMicros  & lt;=, nowMicros;   }

RateLimiter默认实现类的queryEarliestAvailable是取成员变量nextFreeTicketMicros

获取令牌并计算需要等待时间操作:

final  long  reserveAndGetWaitLength(时间允许,int  long  nowMicros), {//获才能取下次可获取时间   long 才能;momentAvailable =, reserveEarliestAvailable(允许,,nowMicros);//计才能算当前线程需要休眠时间   return 才能;马克斯(momentAvailable 安康;nowMicros,, 0);   } , final  long  reserveEarliestAvailable (int  requiredPermits, long  nowMicros), {//重才能新计算桶内令牌数storedPermits   重新同步才能(nowMicros);   long 才能;returnValue =, nextFreeTicketMicros;//本才能次消耗的令牌数   double 才能;storedPermitsToSpend =, min (this.storedPermits requiredPermits也);//重才能新计算下次可获取时间nextFreeTicketMicros   double 才能;freshPermits =, requiredPermits 作用;storedPermitsToSpend;   ,long  waitMicros =,,,storedPermitsToWaitTime (this.storedPermits, storedPermitsToSpend)   ,,,,,+,(长),(freshPermits  *, stableIntervalMicros);      时间=this.nextFreeTicketMicros 才能;LongMath.saturatedAdd (waitMicros nextFreeTicketMicros也);//减才能少桶内令牌数   this.storedPermits 才能;-=,storedPermitsToSpend;   return 才能;returnValue;   以前,}

使用springmvc怎么实现一个限流拦截器