zoukankan      html  css  js  c++  java
  • Guava RateLimiter + AOP注解实现单机限流

    依赖:

            <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

  • 相关阅读:
    k8spod资源的基础管理操作
    k8s名称空间资源
    bzoj5011: [Jx2017]颜色
    bzoj5010: [Fjoi2017]矩阵填数
    bzoj5008: 方师傅的房子
    bzoj5007: TCP协议
    bzoj5003: 与链 5004: 开锁魔法II 5005:乒乓游戏
    bzoj5020: [THUWC 2017]在美妙的数学王国中畅游
    bzoj5006: [THUWC2017 Bipartite]随机二分图
    bzoj4480: [Jsoi2013]快乐的jyy
  • 原文地址:https://www.cnblogs.com/ooo0/p/15013894.html
Copyright © 2011-2022 走看看