API 限流算法详解:令牌桶、漏桶、滑动窗口

API 限流算法详解:令牌桶、漏桶、滑动窗口

API 设计 2026-06-27 10 分钟

API 限流算法详解:令牌桶、漏桶、滑动窗口

限流是保护 API 的重要手段。本文介绍三种限流算法。

1. 令牌桶

固定速率往桶里放令牌,请求需要消耗令牌。

public class TokenBucket {
    private final int capacity;
    private final int rate;
    private int tokens;
    private long lastRefillTime;
    
    public synchronized boolean tryAcquire() {
        refill();
        if (tokens > 0) {
            tokens--;
            return true;
        }
        return false;
    }
    
    private void refill() {
        long now = System.currentTimeMillis();
        int newTokens = (int) ((now - lastRefillTime) / 1000 * rate);
        tokens = Math.min(capacity, tokens + newTokens);
        lastRefillTime = now;
    }
}

2. 漏桶

请求进入漏桶,以固定速率流出。

public class LeakyBucket {
    private final int capacity;
    private final int rate;
    private int water;
    private long lastLeakTime;
    
    public synchronized boolean tryAcquire() {
        leak();
        if (water < capacity) {
            water++;
            return true;
        }
        return false;
    }
    
    private void leak() {
        long now = System.currentTimeMillis();
        int leaked = (int) ((now - lastLeakTime) / 1000 * rate);
        water = Math.max(0, water - leaked);
        lastLeakTime = now;
    }
}

3. 滑动窗口

在时间窗口内限制请求数量。

public class SlidingWindow {
    private final int limit;
    private final long windowSize;
    private final Queue<Long> timestamps = new LinkedList<>();
    
    public synchronized boolean tryAcquire() {
        long now = System.currentTimeMillis();
        
        // 移除过期的请求
        while (!timestamps.isEmpty() && timestamps.peek() < now - windowSize) {
            timestamps.poll();
        }
        
        if (timestamps.size() < limit) {
            timestamps.offer(now);
            return true;
        }
        return false;
    }
}

算法对比

算法 特点 适用场景
令牌桶 允许突发流量 API 限流
漏桶 平滑流量 流量整形
滑动窗口 精确控制 精确限流

Spring Boot 实现

@Component
public class RateLimitInterceptor implements HandlerInterceptor {
    private final TokenBucket bucket = new TokenBucket(100, 10);
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (!bucket.tryAcquire()) {
            response.setStatus(429);
            return false;
        }
        return true;
    }
}

总结

限流是保护 API 的重要手段。根据场景选择合适的算法,防止服务被过载。

📚 相关文章