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

  • 相关阅读:
    QML中的states用法
    mako的namespace(四)
    Dynamics CRM2013 按钮自定义开发工具 Ribbon Workbench 介绍
    CRM 导入导出附件上传大小限制控制
    插件(plugin)调试技巧及注意事项
    Dynamics CRM2013 自定义开发工具 Dynamics XRM Tools 介绍
    传递正能量,拒绝负能量!加油
    让人无语的编程环境
    转NET(C#):线程本地存储(ThreadLocal Storage)之ThreadStatic, LocalDataStoreSlot和ThreadLocal<T>
    转javaThreadLocal
  • 原文地址:https://www.cnblogs.com/ooo0/p/15013894.html
Copyright © 2011-2022 走看看