频率限制
This commit is contained in:
19
src/main/java/com/sqx/common/annotation/Limiting.java
Normal file
19
src/main/java/com/sqx/common/annotation/Limiting.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.sqx.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 限流注解
|
||||
* @author GYJoker
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Limiting {
|
||||
// 默认每秒放入桶中的token
|
||||
double limitNum() default 20;
|
||||
|
||||
String name() default "";
|
||||
}
|
||||
61
src/main/java/com/sqx/common/aspect/RateLimitAspect.java
Normal file
61
src/main/java/com/sqx/common/aspect/RateLimitAspect.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package com.sqx.common.aspect;
|
||||
|
||||
import com.google.common.util.concurrent.RateLimiter;
|
||||
import com.sqx.common.annotation.Limiting;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.Signature;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author GYJoker
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RateLimitAspect {
|
||||
private ConcurrentHashMap<String, RateLimiter> RATE_LIMITER = new ConcurrentHashMap<>();
|
||||
private RateLimiter rateLimiter;
|
||||
|
||||
@Pointcut("@annotation(com.sqx.common.annotation.Limiting)")
|
||||
public void serviceLimit() {
|
||||
}
|
||||
|
||||
@Around("serviceLimit()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
//获取拦截的方法名
|
||||
Signature sig = point.getSignature();
|
||||
//获取拦截的方法名
|
||||
MethodSignature msig = (MethodSignature) sig;
|
||||
//返回被织入增加处理目标对象
|
||||
Object target = point.getTarget();
|
||||
//为了获取注解信息
|
||||
Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
|
||||
//获取注解信息
|
||||
Limiting annotation = currentMethod.getAnnotation(Limiting.class);
|
||||
//获取注解每秒加入桶中的token
|
||||
double limitNum = annotation.limitNum();
|
||||
// 注解所在方法名区分不同的限流策略
|
||||
String functionName = msig.getName();
|
||||
|
||||
if (RATE_LIMITER.containsKey(functionName)) {
|
||||
rateLimiter = RATE_LIMITER.get(functionName);
|
||||
} else {
|
||||
RATE_LIMITER.put(functionName, RateLimiter.create(limitNum));
|
||||
rateLimiter = RATE_LIMITER.get(functionName);
|
||||
}
|
||||
if (rateLimiter.tryAcquire()) {
|
||||
return point.proceed();
|
||||
} else {
|
||||
log.info("超过限流限制, {}", functionName);
|
||||
throw new RuntimeException("服务器繁忙,请稍后再试。");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user