欢迎查看Eetal的第十九篇博客–使用HandlerInterceptor和RateLimiter进行限流
为什么使用拦截器
目前网上有博客使用的是aop,但是因为我项目里使用了shiro进行权限验证
shiro的过滤器链优先级是低于spring的过滤器的
所以根据约定优于配置,直接使用过滤器就不需要去配置shiro的一些映射和过滤器的优先级
同时网上博客基于aop为注解添加令牌桶效率的属性是有bug的,因为springMVC多线程是Method级别
而在aop的切面里创建rateLimiter或者为拿到的method对象的annotation对象绑定一个rateLimiter都会有线程问题
基于以上,把ratelimiter拿到拦截器,如果要定义不同rateLimiter可以改为定义多个拦截器和注解
常见限流算法
常见的限流方法有信号量计数器(Semaphore)计数当前线程个数
漏桶算法—使用一个容器保存进来的任务,按照固定速率流出任务,桶满时新加入的任务直接流出
令牌桶算法—使用一个容器存储令牌,按照固定速率生产令牌,令牌桶满时直接丢弃新生成令牌,任务进来以后尝试获取令牌,获取成功的任务开始执行
计数器较麻烦,需要维护实时记录线程数,完成时进行维护
对比令牌桶和漏桶,漏桶算法无法解决当容量空闲了一段时间以后,大量任务一起进来时,执行的平均效率低下的问题,而令牌桶的令牌生成速率是固定的
rateLimiter介绍
RateLimiter是guava提供的基于令牌桶算法的实现类
create(Double permitsPerSecond)方法根据给定的(令牌:单位时间(1s))比例为令牌生成速率
tryAcquire()方法尝试获取一个令牌,立即返回true/false,不阻塞,重载方法具备设置获取令牌个数、获取最大等待时间等参数
acquire()方法与tryAcquire类似,但是会阻塞,尝试获取一个令牌,没有时则阻塞直到获取成功
注解创建
1 | @Target(ElementType.METHOD) |
拦截器
1 | public class RateLimitInterceptor implements HandlerInterceptor { |
springBoot拦截器配置
1 | @Configuration |
开始使用
1 | @RateLimit(1000) //最大等待时间1s |
请移步
个人主页: yangyitao.top