问题产生,当调用一个接口很频繁的时候,比如每秒调用一个接口100次。业务提现在抢购等。这时我们的服务器处理不过来就会拒绝服务,宕机等等。。。显然这不是我们需要的。
因此产生了限流这个。限流是什么呢,就是我只是接收那么多,多的就是等待,排队,或者拒绝,然你等待,不进入服务。。。
直接上代码:
@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); } }
使用方法就是在你控制器上面加上你注解即可:
@RateLimit(limintNum = 10)
这样就起到了限流作用...这对于每秒请求频繁,并发量大的接口有好处。。。毋庸置疑佬。。。