問題產生,當調用一個接口很頻繁的時候,好比每秒調用一個接口100次。業務提如今搶購等。這時咱們的服務器處理不過來就會拒絕服務,宕機等等。。。顯然這不是咱們須要的。json
所以產生了限流這個。限流是什麼呢,就是我只是接收那麼多,多的就是等待,排隊,或者拒絕,然你等待,不進入服務。。。服務器
直接上代碼:併發
@Inherited @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RateLimit { /** * 默認每秒支持100個 * @return */ int limintNum() default 100; }
/** * 限流 切面枚舉實現 * * @author mingge * */ @Component @Scope @Aspect @Slf4j public class RateLimitAspect { /** * //用來存放不一樣接口的RateLimiter(key爲接口名稱,value爲RateLimiter) */ private ConcurrentHashMap<String, RateLimiter> map = new ConcurrentHashMap<>(); private static final String POINT = "execution (* com.mingge..*.controller..*.*(..))"; private static ObjectMapper objectMapper = new ObjectMapper(); private RateLimiter rateLimiter; @Autowired private HttpServletResponse response; @Pointcut(POINT) public void serviceLimit() { } @Around("serviceLimit()") public Object around(ProceedingJoinPoint joinPoint) throws NoSuchMethodException { Object obj = null; //獲取攔截的方法名 Signature sig = joinPoint.getSignature(); //獲取攔截的方法名 MethodSignature msig = (MethodSignature) sig; //返回被織入增長處理目標對象 Object target = joinPoint.getTarget(); //爲了獲取註解信息 Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes()); //獲取註解信息 RateLimit annotation = currentMethod.getAnnotation(RateLimit.class); //獲取註解每秒加入桶中的token int limitNum = annotation.limintNum(); // 註解所在方法名區分不一樣的限流策略 String functionName = msig.getName(); //獲取rateLimiter if(map.containsKey(functionName)){ rateLimiter = map.get(functionName); }else { map.put(functionName, RateLimiter.create(limitNum)); rateLimiter = map.get(functionName); } try { if (rateLimiter.tryAcquire()) { //執行方法 obj = joinPoint.proceed(); } else { BaseVO vo=new BaseVO(); vo.setCode(100001); vo.setMessage("系統繁忙,請稍後再試!"); //拒絕了請求(服務降級) String result = objectMapper.writeValueAsString(vo); log.info("拒絕了請求:" + result); outErrorResult(result); } } catch (Throwable throwable) { throwable.printStackTrace(); } return obj; } //將結果返回 public void outErrorResult(String result) { response.setContentType("application/json;charset=UTF-8"); try (ServletOutputStream outputStream = response.getOutputStream()) { outputStream.write(result.getBytes("utf-8")); } catch (IOException e) { e.printStackTrace(); } } static { objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); } }
使用方法就是在你控制器上面加上你註解便可:app
@RateLimit(limintNum = 10)
這樣就起到了限流做用...這對於每秒請求頻繁,併發量大的接口有好處。。。毋庸置疑佬。。。ui