crossoverJie/JCSprout · warning · RuntimeException
request has bean limit
Error message
request has bean limit
What it means
Thrown by the CommonAspect @Before advice when redisLimit.limit() returns false, meaning the rate-limit check denied the request. This is the intended rate-limiting behaviour (the typo 'bean' should read 'been'): the caller has exceeded the configured request rate within the time window, so the aspect aborts the method invocation with a RuntimeException. It surfaces as a 500 to the HTTP caller unless caught by a controller advice.
Source
Thrown at MD/distributed/Distributed-Limit.md:458
private static Logger logger = LoggerFactory.getLogger(CommonAspect.class);
@Autowired
private RedisLimit redisLimit ;
@Pointcut("@annotation(com.crossoverjie.distributed.annotation.CommonLimit)")
private void check(){}
@Before("check()")
public void before(JoinPoint joinPoint) throws Exception {
if (redisLimit == null) {
throw new NullPointerException("redisLimit is null");
}
boolean limit = redisLimit.limit();
if (!limit) {
logger.warn("request has bean limit");
throw new RuntimeException("request has bean limit") ;
}
}
}
```
很简单,也是在拦截过程中调用限流。
当然使用时也得扫描到该包:
```java
@ComponentScan(value = "com.crossoverjie.distributed.intercept")
```
### 总结
**限流**在一个高并发大流量的系统中是保护应用的一个利器,成熟的方案也很多,希望对刚了解这一块的朋友提供一些思路。
View on GitHub (pinned to fc4c6e5f6d)
Solutions
- Tune the rate-limit parameters (requests per window) in the @CommonLimit annotation or Redis config to match your traffic profile.
- Add a @ControllerAdvice / @ExceptionHandler that catches this RuntimeException and returns HTTP 429 (Too Many Requests) instead of a 500.
- Ensure the limit key correctly distinguishes clients (forward real IP from proxy headers) so one client does not exhaust the budget for all.
- If the limit is expected, handle it client-side with backoff and retry.
Example fix
// before — caller gets a raw 500
throw new RuntimeException("request has bean limit");
// after — return a proper 429
@ControllerAdvice
public class RateLimitHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> onRateLimit(RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("limit")) {
return ResponseEntity.status(429).body("Rate limit exceeded");
}
throw e;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// No pre-call validation can prevent this — it is the rate limit working as designed. // Instead, track your request rate client-side and back off if approaching the limit.
Try / catch
// Server-side: convert the raw RuntimeException into a proper 429.
@ControllerAdvice
public class RateLimitExceptionHandler {
@ExceptionHandler
public ResponseEntity<String> handle(RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("limit")) {
return ResponseEntity.status(429)
.header("Retry-After", "1")
.body("Rate limit exceeded, please retry later.");
}
throw e;
}
} Prevention
- Tune the @CommonLimit rate parameters to match your expected traffic.
- Add a @ControllerAdvice to convert the RuntimeException into HTTP 429 so clients get a clear signal.
- On the client side, implement exponential backoff when receiving 429 responses.
- Ensure the rate-limit key distinguishes real clients if behind a shared proxy.
When it happens
Trigger: A client calls a @CommonLimit-annotated method more times than the configured Redis-based limit allows within the sliding/fixed window. Under load testing (e.g. JMeter) a large fraction of requests hit this path once the rate budget is exhausted.
Common situations: Rate limit threshold set too low for legitimate traffic. Burst traffic from a single client or a shared NAT egress IP. The limit key (typically IP-based) collides because all requests appear to come from the same source behind a proxy without X-Forwarded-For handling. Load testing without accounting for rate limits.
Related errors
AI-assisted analysis of crossoverJie/JCSprout@fc4c6e5f6d (2026-08-14).
Data as JSON: /api/errors/7db6f4bcf0a97859.
Report an issue: GitHub.