封裝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"; } |