首页 > 其他 > 详细

Guava RateLimiter + AOP注解实现单机限流

时间:2021-07-15 11:52:43      阅读:14      评论:0      收藏:0      [点我收藏+]

 

依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
        </dependency>

 

自定义运行时注解:

import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;

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

    /**
     * @return
     */
    String value() default "";

    /**
     * 每秒向桶中放入令牌的数量   默认最大即不做限流
     *
     * @return
     */
    double perSecond() default Double.MAX_VALUE;

    /**
     * 获取令牌的等待时间  默认0
     *
     * @return
     */
    int timeOut() default 0;

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

 

aop切面进行环绕通知:

import com.google.common.util.concurrent.RateLimiter;
import com.xc.xcspringboot.common.annotation.XcRateLimit;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;

import java.lang.reflect.Method;

@Aspect
@Component
public class XcRateLimitAspect {

    private final static Logger logger = LoggerFactory.getLogger(XcRateLimitAspect.class);

    private RateLimiter rateLimiter = RateLimiter.create(Double.MAX_VALUE);

    /**
     * 定义切点
     * 1、通过扫包切入
     * 2、带有指定注解切入
     */
//    @Pointcut("execution(public * com.xc.xcspringboot.*.*(..))")
    @Pointcut("@annotation(com.xc.xcspringboot.common.annotation.XcRateLimit)")
    public void checkPointcut() {
    }

    @ResponseBody
    @Around(value = "checkPointcut()")
    public Object aroundNotice(ProceedingJoinPoint pjp) throws Throwable {
        logger.info("拦截到了{}方法...", pjp.getSignature().getName());
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        //获取目标方法
        Method targetMethod = methodSignature.getMethod();
        if (targetMethod.isAnnotationPresent(XcRateLimit.class)) {
            //获取目标方法的@LxRateLimit注解
            XcRateLimit lxRateLimit = targetMethod.getAnnotation(XcRateLimit.class);
            rateLimiter.setRate(lxRateLimit.perSecond());
            if (!rateLimiter.tryAcquire(lxRateLimit.timeOut(), lxRateLimit.timeOutUnit()))
                return "同时调用次数过多,请稍后再试!";
        }
        return pjp.proceed();
    }
}

 

在controller中使用自定义注解:

@RestController
@RequestMapping("/testRateLimiter")
@Slf4j
public class TestRateLimiterController {

    @RequestMapping("/testAnnotation")
    @XcRateLimit(perSecond = 1.0, timeOut = 500)
    public String testAnnotation() {
        return "get success";
    }


}

 

参考: https://www.cnblogs.com/myseries/p/12634557.html

Guava RateLimiter + AOP注解实现单机限流

原文:https://www.cnblogs.com/ooo0/p/15013894.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!