zoukankan      html  css  js  c++  java
  • 利用guava封装RateLimiter 令牌桶算法(AOP实现)

    该文只封装AOP的实现方式,也可通过拦截器,过滤器等实现.

    自定义注解封装RateLimiter.实例:

    @RequestMapping("/myOrder")
    @ExtRateLimiter(value = 10.0, timeOut = 500)
    public String myOrder() throws InterruptedException {
               System.out.println("myOrder");
               return "SUCCESS";
    
    }

    自定义注解:

    @Target(value = ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ExtRateLimiter {
    
          double value();
    
          long timeOut();
    
    }

    编写AOP

    @Aspect
    @Component
    public class RateLimiterAop {
    
          // 存放接口是否已经存在
          private static ConcurrentHashMap<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<String, RateLimiter>();
    
          @Pointcut("execution(public * com.it.api.*.*(..))")
          public void rlAop() {
          }
    
     
          @Around("rlAop()")
          public Object doBefore(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
               MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
               // 使用Java反射技术获取方法上是否有@ExtRateLimiter注解类
               ExtRateLimiter extRateLimiter = signature.getMethod().getDeclaredAnnotation(ExtRateLimiter.class);
               if (extRateLimiter == null) {
                     // 正常执行方法
                     Object proceed = proceedingJoinPoint.proceed();
                     return proceed;
               }
               // ############获取注解上的参数 配置固定速率 ###############
               // 获取配置的速率
               double value = extRateLimiter.value();
               // 获取等待令牌等待时间
               long timeOut = extRateLimiter.timeOut();
               RateLimiter rateLimiter = getRateLimiter(value, timeOut);
               // 判断令牌桶获取token 是否超时
               boolean tryAcquire = rateLimiter.tryAcquire(timeOut, TimeUnit.MILLISECONDS);
               if (!tryAcquire) {
                     serviceDowng();
                     return null;
               }
               // 获取到令牌,直接执行..
               Object proceed = proceedingJoinPoint.proceed();
               return proceed;
          }
    
     
    
          // 获取RateLimiter对象
          private RateLimiter getRateLimiter(double value, long timeOut) {
               // 获取当前URL
               ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
               HttpServletRequest request = attributes.getRequest();
               String requestURI = request.getRequestURI();
               RateLimiter rateLimiter = null;
               if (!rateLimiterMap.containsKey(requestURI)) {
                     // 开启令牌通限流
                     rateLimiter = RateLimiter.create(value); // 独立线程
                     rateLimiterMap.put(requestURI, rateLimiter);
               } else {
                     rateLimiter = rateLimiterMap.get(requestURI);
               }
               return rateLimiter;
          }
    
     
    
          // 服务降级
          private void serviceDowng() throws IOException {
               // 执行服务降级处理
               System.out.println("执行降级方法,亲,服务器忙!请稍后重试!");
               ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
               HttpServletResponse response = attributes.getResponse();
               response.setHeader("Content-type", "text/html;charset=UTF-8");
               PrintWriter writer = response.getWriter();
               try {
                     writer.println("执行降级方法,亲,服务器忙!请稍后重试!");
               } catch (Exception e) {
               } finally {
                     writer.close();
               }
          }
    
    
          public static void main(String[] args) {
               // 使用Java反射技术获取方法上是否有@ExtRateLimiter注解类
               ExtRateLimiter extRateLimiter = IndexController.class.getClass().getAnnotation(ExtRateLimiter.class);
               System.out.println(extRateLimiter);
          }
    
    }

    运行效果:

    @RequestMapping("/myOrder")
    @ExtRateLimiter(value = 10.0, timeOut = 500)
    public String myOrder() throws InterruptedException {
               System.out.println("myOrder");
               return "SUCCESS";
    }
  • 相关阅读:
    PowerDesigner反向生成物理数据模型
    10个JavaScript的难点
    Golang数组拼接为字符串
    Golang对元素slice并去重
    golang获取开始日期和结束日期的所有日期列表
    go数组取交集截取
    golang学习笔记
    go语言time包简单使用
    windows为GO设置代理解决go get缓慢
    sublime使用笔记
  • 原文地址:https://www.cnblogs.com/47Gamer/p/13960237.html
Copyright © 2011-2022 走看看