|
@@ -38,9 +38,9 @@ public class RateLimitInterceptor extends AbstractInterceptor {
|
|
String endpoint = request.getServletPath();
|
|
String endpoint = request.getServletPath();
|
|
String device = getDeviceIdOrIpAddress(request);
|
|
String device = getDeviceIdOrIpAddress(request);
|
|
String user = getUserIdentity(request);
|
|
String user = getUserIdentity(request);
|
|
- // 所有限流规则需要全部匹配才通过
|
|
|
|
- // 已通过限流堆栈
|
|
|
|
|
|
+ // 已通过限流验证堆栈
|
|
Deque<RateLimiter> stack = new ArrayDeque<>();
|
|
Deque<RateLimiter> stack = new ArrayDeque<>();
|
|
|
|
+ // 所有限流规则需要全部匹配才通过
|
|
for (RateLimitRule rule : ac.getRateLimit()) {
|
|
for (RateLimitRule rule : ac.getRateLimit()) {
|
|
String target = null;
|
|
String target = null;
|
|
if (rule.getTarget() == RateLimitTarget.DEVICE) {
|
|
if (rule.getTarget() == RateLimitTarget.DEVICE) {
|
|
@@ -50,12 +50,15 @@ public class RateLimitInterceptor extends AbstractInterceptor {
|
|
}
|
|
}
|
|
RateLimiter limiter = rateLimitService.getRateLimiter(endpoint, target, rule);
|
|
RateLimiter limiter = rateLimitService.getRateLimiter(endpoint, target, rule);
|
|
if (limiter.acquire()) {
|
|
if (limiter.acquire()) {
|
|
|
|
+ //限流验证成功则进入堆栈
|
|
stack.push(limiter);
|
|
stack.push(limiter);
|
|
} else {
|
|
} else {
|
|
|
|
+ //限流验证失败时,已通过的堆栈需要释放
|
|
while (!stack.isEmpty()) {
|
|
while (!stack.isEmpty()) {
|
|
stack.pop().release();
|
|
stack.pop().release();
|
|
}
|
|
}
|
|
- log.warn("Rate limited: endpoint={}, rule={}, target={}", endpoint, rule.toString(), target);
|
|
|
|
|
|
+ log.warn("Rate limited: endpoint={}, rule={}, target={}", endpoint, rule.toString(),
|
|
|
|
+ StringUtils.trimToEmpty(target));
|
|
throw DefaultExceptionEnum.RATE_LIMITED.exception();
|
|
throw DefaultExceptionEnum.RATE_LIMITED.exception();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -66,9 +69,9 @@ public class RateLimitInterceptor extends AbstractInterceptor {
|
|
@Override
|
|
@Override
|
|
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
|
|
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
|
|
Exception ex) {
|
|
Exception ex) {
|
|
|
|
+ //接口请求完成时,已通过的堆栈需要释放
|
|
Deque<RateLimiter> stack = RequestUtil.getAttribute(request, ApiConstant.ATTRIBUTE_RATE_LIMITER_STACK);
|
|
Deque<RateLimiter> stack = RequestUtil.getAttribute(request, ApiConstant.ATTRIBUTE_RATE_LIMITER_STACK);
|
|
if (stack != null) {
|
|
if (stack != null) {
|
|
- log.debug("Rate limit stack size: " + stack.size());
|
|
|
|
while (!stack.isEmpty()) {
|
|
while (!stack.isEmpty()) {
|
|
stack.pop().release();
|
|
stack.pop().release();
|
|
}
|
|
}
|
|
@@ -85,6 +88,7 @@ public class RateLimitInterceptor extends AbstractInterceptor {
|
|
}
|
|
}
|
|
|
|
|
|
private String getUserIdentity(HttpServletRequest request) {
|
|
private String getUserIdentity(HttpServletRequest request) {
|
|
|
|
+ // 有鉴权信息的情况下,使用签名中的identity作为访问用户标识
|
|
AccessEntity accessEntity = RequestUtil.getAttribute(request, ApiConstant.ATTRIBUTE_ACCESS_ENTITY);
|
|
AccessEntity accessEntity = RequestUtil.getAttribute(request, ApiConstant.ATTRIBUTE_ACCESS_ENTITY);
|
|
if (accessEntity != null) {
|
|
if (accessEntity != null) {
|
|
return accessEntity.getIdentity();
|
|
return accessEntity.getIdentity();
|