频率限制1
This commit is contained in:
@@ -13,7 +13,5 @@ import java.lang.annotation.Target;
|
|||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Limiting {
|
public @interface Limiting {
|
||||||
// 默认每秒放入桶中的token
|
// 默认每秒放入桶中的token
|
||||||
double limitNum() default 20;
|
double limitNum() default 10;
|
||||||
|
|
||||||
String name() default "";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ import org.aspectj.lang.annotation.Aspect;
|
|||||||
import org.aspectj.lang.annotation.Pointcut;
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@@ -30,32 +33,29 @@ public class RateLimitAspect {
|
|||||||
|
|
||||||
@Around("serviceLimit()")
|
@Around("serviceLimit()")
|
||||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||||
//获取拦截的方法名
|
// 获取当前请求
|
||||||
Signature sig = point.getSignature();
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
//获取拦截的方法名
|
HttpServletRequest request = attributes.getRequest();
|
||||||
MethodSignature msig = (MethodSignature) sig;
|
// 获取请求的 IP 地址
|
||||||
//返回被织入增加处理目标对象
|
String ip = request.getRemoteAddr();
|
||||||
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)) {
|
// 获取方法上的 @AccessLimit 注解
|
||||||
rateLimiter = RATE_LIMITER.get(functionName);
|
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||||
} else {
|
Method method = signature.getMethod();
|
||||||
RATE_LIMITER.put(functionName, RateLimiter.create(limitNum));
|
Limiting accessLimit = method.getAnnotation(Limiting.class);
|
||||||
rateLimiter = RATE_LIMITER.get(functionName);
|
double permitsPerSecond = accessLimit.limitNum();
|
||||||
}
|
|
||||||
|
// 获取或创建该 IP 对应的 RateLimiter
|
||||||
|
RateLimiter rateLimiter = RATE_LIMITER.computeIfAbsent(ip, k -> RateLimiter.create(permitsPerSecond));
|
||||||
|
|
||||||
|
// 尝试获取许可
|
||||||
if (rateLimiter.tryAcquire()) {
|
if (rateLimiter.tryAcquire()) {
|
||||||
|
// 成功获取许可,继续执行方法
|
||||||
return point.proceed();
|
return point.proceed();
|
||||||
} else {
|
} else {
|
||||||
log.info("超过限流限制, {}", functionName);
|
// 未获取到许可,抛出异常或返回错误信息
|
||||||
throw new RuntimeException("服务器繁忙,请稍后再试。");
|
log.info("IP: {} 请求方法: {} 超过访问频率限制", ip, method.getName());
|
||||||
|
throw new RuntimeException("访问频率过高,请稍后再试");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class AppCourseCollectController extends AbstractController {
|
|||||||
@Login
|
@Login
|
||||||
@PostMapping("/insertCourseCollect")
|
@PostMapping("/insertCourseCollect")
|
||||||
@ApiOperation("app收藏短剧信息")
|
@ApiOperation("app收藏短剧信息")
|
||||||
@Limiting(name = "AppCourseCollectController-insertCourseCollect", limitNum = 25)
|
@Limiting
|
||||||
public Result insertCourseCollect(@RequestBody CourseCollect courseCollect, @RequestAttribute("userId") Long userId) {
|
public Result insertCourseCollect(@RequestBody CourseCollect courseCollect, @RequestAttribute("userId") Long userId) {
|
||||||
courseCollect.setUserId(userId);
|
courseCollect.setUserId(userId);
|
||||||
return courseCollectService.insertCourseCollect(courseCollect);
|
return courseCollectService.insertCourseCollect(courseCollect);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class AppOrdersController extends AbstractController {
|
|||||||
@GetMapping("/insertCourseOrders")
|
@GetMapping("/insertCourseOrders")
|
||||||
@ApiOperation("生成商品订单")
|
@ApiOperation("生成商品订单")
|
||||||
@Debounce(interval = 20000, value = "#userId")
|
@Debounce(interval = 20000, value = "#userId")
|
||||||
@Limiting(name = "AppOrdersController-insertCourseOrders", limitNum = 60)
|
@Limiting
|
||||||
public Result insertCourseOrders(Long courseId,Long courseDetailsId, @RequestAttribute("userId") Long userId) {
|
public Result insertCourseOrders(Long courseId,Long courseDetailsId, @RequestAttribute("userId") Long userId) {
|
||||||
return ordersService.insertCourseOrders(courseId, courseDetailsId,userId);
|
return ordersService.insertCourseOrders(courseId, courseDetailsId,userId);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user