利用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";
}
posted @ 2020-11-11 19:00  47号Gamer丶  阅读(407)  评论(0编辑  收藏  举报