在 Java 中,API 接口限流(Rate Limiting)是非常常见的需求,目的是防止接口被恶意刷爆或保护系统稳定性。下面从常见限流算法、实现方式、主流框架和实战示例几个层面给你一个完整说明。
原理:每 N 秒允许 M 次请求
优点:实现简单
缺点:存在“突刺问题”(窗口边界瞬间打满)
[0s - 1s] 允许 100 次
原理:把时间切分成小格子,统计最近一段时间内的请求
优点:比固定窗口平滑
缺点:实现稍复杂
原理:请求进桶,固定速率流出
特点:流量很平滑,不适合突发流量
原理:
✅ 生产环境首选
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>
RateLimiter limiter = RateLimiter.create(5); // 每秒 5 个请求
@GetMapping("/test")
public String test() {
if (!limiter.tryAcquire()) {
return "被限流了";
}
return "success";
}
✅ 适合:
❌ 不适合分布式
local key = KEYS[1]
local maxToken = tonumber(ARGV[1])
local rate = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local bucket = redis.call("HMGET", key, "tokens", "timestamp")
local tokens = tonumber(bucket[1]) or maxToken
local lastTime = tonumber(bucket[2]) or now
local delta = math.max(0, now - lastTime)
tokens = math.min(maxToken, tokens + delta * rate)
if tokens < 1 then
return 0
else
tokens = tokens - 1
redis.call("HMSET", key, "tokens", tokens, "timestamp", now)
redis.call("EXPIRE", key, 10)
return 1
end
Boolean allowed = redisTemplate.execute(
redisScript,
Collections.singletonList("rate_limit:api"),
10, 1, System.currentTimeMillis() / 1000
);
if (!allowed) {
throw new RuntimeException("请求过于频繁");
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {
int limit() default 5;
int seconds() default 1;
}
@Aspect
@Component
public class RateLimitAspect {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Around("@annotation(rateLimit)")
public Object check(ProceedingJoinPoint pjp, RateLimit rateLimit) throws Throwable {
String key = "rate:" + pjp.getSignature().toLongString();
Long count = redisTemplate.opsForValue().increment(key, 1);
if (count == 1) {
redisTemplate.expire(key, rateLimit.seconds(), TimeUnit.SECONDS);
}
if (count > rateLimit.limit()) {
throw new RuntimeException("接口被限流");
}
return pjp.proceed();
}
}
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
✅ 推荐用于:
| 场景 | 推荐方案 |
|---|---|
| 单体应用 | Guava RateLimiter |
| 分布式系统 | Redis + Lua |
| 微服务 | Gateway 限流 |
| 接口级控制 | AOP + Redis |
| 防止恶意刷接口 | 网关 + IP 限流 |
⚠️
429 Too Many Requests如果你需要:
✅ 完整 Demo 项目
✅ 网关限流实战
✅ IP 限流 + 黑名单
告诉我你的 具体场景(单体 / 微服务 / 网关 / Spring Boot 版本),我可以给你更精确的方案。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。