springboot整合RateLimiter限流(令牌桶)使用aop的方式拦截并动态修改限流值

添加依赖

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.2-jre</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

自定义限流拦截注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Limiting {

    //默认每秒放入桶中的token(0.5也就是2秒1次)
    double alias() default 0;
}

使用@PostConstruct和临时缓存充当从数据库读取数据

@Data
@NoArgsConstructor
@AllArgsConstructor
public class RateLimit {

    private Integer rateId;

    /**
     * 限流名称(类名)
     */
    private String rateName;

    /**
     * 限流组名(组名,唯一)
     */
    private String rateGroup;

    /**
     * 方法名称
     */
    private String methodName;

    /**
     * 限流量
     */
    private Double limit;

    /**
     * 状态(0正常 1暂停)
     */
    private Integer state;

    /**
     * 备注信息
     */
    private String remark;

}

@Component
public class RateLimitCache {

    public static Map<Integer,RateLimit> map = new ConcurrentHashMap<>();

    @PostConstruct
    public void init(){
        RateLimit rateLimit = new RateLimit(1,"rate","测试组名","rateLimit",3.0,0,"");
        map.put(1,rateLimit);
    }

}

aop拦截注解并设置限流

@Slf4j
@Component
@Aspect
public class RateLimitAspect {

    private ConcurrentHashMap<String, RateLimiter> limitMap = new ConcurrentHashMap<>();
    private RateLimiter rateLimiter;

    @Pointcut("@annotation(com.bsj.demo.test.annotation.Limiting)")
    public void serviceLimit() {

    }
    @Around("serviceLimit()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        //获取拦截的签名
        Signature sig = point.getSignature();
        MethodSignature msg = (MethodSignature) sig;
        //返回被植入增加处理目标对象
        Object target = point.getTarget();
        //获取注解信息
        Method method = target.getClass().getMethod(msg.getName(), msg.getParameterTypes());
        //获取注解中每秒加入令牌桶中的token
        Limiting annotation = method.getAnnotation(Limiting.class);
        //按照配置取限流次数
        double limitNum = annotation.alias();
        log.info("------------limitNum:" + limitNum);
		Class<?> aClass = target.getClass();
        // 获取Controller注解
        Controller controller = aClass.getAnnotation(Controller.class);
        String value = controller.value();
        String name = method.getName();
        //这里是处理数据与限流之间的关系,我就随便写写匹配
        RateLimit rateLimit = RateLimitCache.map.get(1);
        if (rateLimit.getRateName().equals(value) && rateLimit.getMethodName().equals(name) && !limitMap.containsKey("abc")){
            log.info("获取值为:"+rateLimit.getLimit());
            limitMap.put("abc", RateLimiter.create(rateLimit.getLimit()));
            rateLimiter = limitMap.get("abc");
        }
log.info("===================--------:"+rateLimiter.getRate());




        boolean tryAcquire = rateLimiter.tryAcquire(10);

        log.info("rateLimiter.tryAcquire(10):"+tryAcquire);

        if (!tryAcquire) {
            log.info("获取不到令牌拉---------------");
            return "请求过于频繁";
        }

        return point.proceed();
    }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值