1. 限流算法深度解析与网关实践指南
在分布式系统架构中,流量控制是保障系统稳定性的关键防线。作为一名经历过多次大促流量冲击的架构师,我深刻体会到合理的限流策略对于系统的重要性。本文将基于我在多个千万级用户项目中的实践经验,深入剖析主流限流算法的实现原理,并分享在API网关中的落地实践。
1.1 为什么需要限流?
想象一下高速公路的收费站:如果没有限流措施,节假日高峰时段所有车辆同时涌入,必然导致系统瘫痪。同理,在软件系统中:
- 突发流量:秒杀活动、热点事件引发的瞬时高并发
- 异常流量:爬虫攻击、客户端异常导致的重复请求
- 依赖故障:下游服务响应变慢导致请求堆积
这些场景都会导致:
- 线程池耗尽,服务不可用
- 级联故障引发雪崩效应
- 数据库连接被打满
通过限流,我们可以:
- 保护核心业务不被突发流量击垮
- 给系统故障恢复争取缓冲时间
- 公平分配系统资源,避免少数用户占用全部容量
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心限流算法详解
2.1 计数器算法:最基础的限流实现
2.1.1 实现原理
计数器算法就像体育场的入场检票:
- 每个时间窗口(如1分钟)设置一个计数器
- 请求到达时计数器+1
- 超过阈值则拒绝请求
- 时间窗口结束时计数器归零
java复制public class CounterLimiter {
private final int limit = 100; // 窗口阈值
private final long windowSize = 60_000; // 1分钟窗口
private int counter = 0;
private long windowStart = System.currentTimeMillis();
public synchronized boolean tryAcquire() {
long now = System.currentTimeMillis();
if (now - windowStart > windowSize) {
counter = 0;
windowStart = now;
}
if (counter < limit) {
counter++;
return true;
}
return false;
}
}
2.1.2 临界问题与解决方案
该算法存在明显的时间窗口临界问题:
- 假设限流100次/分钟
- 第59秒突然涌入100个请求
- 下一个窗口的第1秒又涌入100个请求
- 实际在2秒内处理了200个请求
优化方案:使用滑动窗口算法
2.2 滑动窗口算法:解决临界问题
2.2.1 实现原理
将时间窗口细分为多个格子(如6秒一个格子),统计最近N个格子的请求总数:
code复制窗口:60秒 | 格子:6秒/个
[20][15][25][30][18][22][28][32][35][40]
↑ 最近75次请求(格子9+10)
java复制public class SlidingWindowLimiter {
private final int limit = 100;
private final int slotCount = 10;
private final AtomicInteger[] slots = new AtomicInteger[slotCount];
private volatile long lastRotateTime = System.currentTimeMillis();
public SlidingWindowLimiter() {
for (int i = 0; i < slotCount; i++) {
slots[i] = new AtomicInteger(0);
}
}
public synchronized boolean tryAcquire() {
rotateWindow();
int total = Arrays.stream(slots).mapToInt(Atom
