1.最终效果
例如:@AccessFast(qps = 10),在注解中配置qps参数,每秒最多10次request请求.即可实现限流效果
@AccessFast(qps = 10)
@ApiOperation(value = "根据id查询详情")
@RequestMapping(value = "/info/{id}", method = RequestMethod.POST)
public R info1(@PathVariable(value = "id") Long id) {
return kidGrowReportService.getKidGrowReportById(id);
}
2.具体代码
(1)注解类 AccessFast
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessFast {
int qps() default -1;//每秒限制最多多少个请求 qps=-1表示不限流-目前的限流器针对具体uri
int timeout() default -1;//超时限制,单位为毫秒---如果有超时限制,则一定为非阻塞,block参数无需考虑
boolean block() default true;//是否阻塞
}
(2)拦截器
//限流器容器
private Map<String, RateLimiter> rateMaps = Maps.newConcurrentMap();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (null != handler) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
if (null != method) {
// 获取限流注解
AccessFast methodAnnotation = method.getAnnotation(AccessFast.class);
if (methodAnnotation != null) {
int qps = methodAnnotation.qps();
int timeout = methodAnnotation.timeout();
boolean block = methodAnnotation.block();
if (qps != -1) {//限流
String requestURI = request.getRequestURI();
RateLimiter rateLimiter = rateMaps.get(requestURI);
if (rateLimiter == null) {
rateLimiter = RateLimiter.create(qps);
rateMaps.put(requestURI, rateLimiter);
return true;
}
if (timeout != -1) {//非阻塞
logger.info("AccessFast | not block");
if (rateLimiter.tryAcquire(timeout, TimeUnit.MILLISECONDS)) {
logger.info("AccessFast | success");
return true;
} else {
logger.info("AccessFast | not block timeout:{}", timeout);
return false;
}
} else {
if (block){//阻塞
double acquire = rateLimiter.acquire();
logger.info("AccessFast | block time:{} | acquire", acquire);
}else {
if(rateLimiter.tryAcquire()){
logger.info("AccessFast | not block | tryAcquire");
}
}
}
}
return true;
}
}
}
}