在Java中实现接口限流可以通过多种算法,包括计数器限流、时间窗口限流、漏桶算法和令牌桶算法。下面是一些常见的限流实现方法:
1. 计数器限流
使用`AtomicInteger`来记录每个时间窗口内的请求数量,并与预设的阈值进行比较。
public class CounterLimiter {
private int limit;
private AtomicInteger counter;
public CounterLimiter(int limit) {
this.limit = limit;
this.counter = new AtomicInteger(0);
}
public boolean allowRequest() {
int currentCount = counter.incrementAndGet();
if (currentCount > limit) {
counter.decrementAndGet();
return false;
}
return true;
}
}
2. 令牌桶限流
令牌桶算法通过一个固定大小的桶以固定速率生成令牌。
import com.google.common.util.concurrent.RateLimiter;
public class RateLimiterExample {
private static final RateLimiter limiter = RateLimiter.create(1); // 允许每秒最多1个任务
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
limiter.acquire(); // 请求令牌,超过许可会被阻塞
new Thread(new TestRateLimiter()).start();
}
}
}
3. 时间窗口限流
缓存请求时间,并在每次请求时校验一定时间窗口内的请求次数。
public class TimeWindowRateLimiter {
private int maxRequests;
private long[] cache;
public TimeWindowRateLimiter(int maxRequests) {
this.maxRequests = maxRequests;
this.cache = new long[maxRequests];
}
public boolean allowRequest() {
long currentTime = System.currentTimeMillis();
// 清除过期的请求时间
for (int i = 0; i < maxRequests; i++) {
if (currentTime - cache[i] > 10000) { // 10秒窗口
cache[i] = currentTime;
}
}
// 检查最近三次请求是否超过限制
for (int i = 0; i < maxRequests - 1; i++) {
if (currentTime - cache[i] <= 10000) {
return false;
}
}
return true;
}
}
4. 使用Guava的`RateLimiter`注解
Guava库提供了`RateLimiter`类,可以方便地通过注解实现限流。
import com.google.common.util.concurrent.RateLimiter;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestLimiter {
double QPS() default 10D; // 每秒创建令牌个数
long timeout() default 500; // 获取令牌等待超时时间
TimeUnit timeunit() default TimeUnit.MILLISECONDS; // 超时时间单位
}
5. 使用拦截器进行限流
可以在方法调用前通过拦截器进行限流处理。
public class RateLimiterInterceptor {
private RateLimiter rateLimiter = RateLimiter.create(1); // 允许每秒最多1个任务
public void intercept(JoinPoint joinPoint) throws Throwable {
if (!rateLimiter.tryAcquire()) {
throw new RuntimeException("Too many requests, please try again later.");
}
joinPoint.proceed();
}
}
以上是Java中实现接口限流的一些常见方法。你可以根据具体的应用场景选择合适的算法进行实现。需要注意的是,这些方法可能需要根据实际需求进行调整和优化