互聯網高併發解決方案03-高併發服務限流特技-純手寫打造RateLimiter註解框架

封裝RateLimiter

自定義註解封裝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.ratelimiter.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";

}

發佈了365 篇原創文章 · 獲贊 23 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章