使用HandlerInterceptor和RateLimiter进行限流

本文介绍了为何选择使用拦截器进行限流,而非AOP,主要原因是避免与Shiro的过滤器冲突及AOP线程安全问题。文中详细讲解了限流算法,如信号量、漏桶和令牌桶,并重点阐述了Guava的RateLimiter令牌桶实现。通过创建注解和拦截器,配合SpringBoot的配置,实现了基于RateLimiter的限流功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


欢迎查看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类似,但是会阻塞,尝试获取一个令牌,没有时则阻塞直到获取成功

注解创建

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimit {
   
   
 
    /**
     * 获取令牌的等待时间  默认0
     * @return
     */
	int value() default 0;

 
    /**
     * 超时时间单位
     * @return
     */
    TimeUnit timeOutUnit() default TimeUnit.MILLISECONDS;
    
}

拦截器

public class RateLimitInterceptor implements HandlerInterceptor {
   
   
 
    private final static Logger logger = L
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值