什么是自适应限流?
结论:自适应限流(Adaptive Rate Limiting)不预设固定 QPS 阈值,而是根据系统实时指标(CPU、load、RT、并发线程数、排队长度)动态计算当前能承受的速率。它解决的是「固定阈值在容量变化时要么过松要么过严」的问题,代价是算法复杂、容易抖动。
一、固定阈值为什么不够
| 场景 | 固定阈值的表现 |
|---|---|
| 下游变慢(DB RT 从 5 ms 涨到 50 ms) | 阈值不变,线程池被打满,雪崩 |
| 扩容一半机器 | 总阈值需人工改配置,改慢了就过载 |
| 大促冷启动 | 按全量阈值放行,直接压垮刚启动的实例 |
| 慢 SQL 偶发 | 指标早已恶化,固定阈值毫无感知 |
二、反馈环
┌───────────────────────────────────────────┐
│ │
▼ │
┌─────────┐ 放行速率 ┌──────────┐ 观测指标 │
│ 限流器 │ ──────────► │ 系统 │ ───────────┤
│(动态阈值)│ │ CPU / RT │ │
└─────────┘ ◄────────────│ 并发/队列 │ │
调整阈值 └──────────┘ │
│
阈值 = f(CPU, load1, RT_p99, inflight, queue) ───┘
两条主流思路:
- 基于负载:CPU 超过 80% 或 load 超过核数就线性降额(Sentinel 系统规则)。
- 基于时延:用 Little's Law(
并发 = QPS × RT)估算容量,RT 上升就压低 QPS(BBR 类算法)。
三、Sentinel 系统自适应
system:
- highestSystemLoad: 4.0 # load1 超过 4 开始降
avgRt: 200 # 平均 RT 超过 200ms 开始降
maxThread: 500 # 并发线程数上限
qps: 3000 # 入口总 QPS 上限
checkIntervalMs: 1000
Sentinel 会取这些指标中最严格的一个,动态压低准入阈值。它的取向是「宁可少放一点,也不让系统进入不可恢复的过载」。
四、基于时延的自适应实现
public class AdaptiveLimiter {
private final AtomicLong inflight = new AtomicLong();
private volatile double limit = 1000; // 初始容量估计
private volatile long minRt = Long.MAX_VALUE;
private volatile long maxRt = 0;
private final AtomicLong sample = new AtomicLong();
public boolean tryAcquire() {
return inflight.get() < limit;
}
public void onEnter() {
inflight.incrementAndGet();
}
public void onExit(long rtMs) {
inflight.decrementAndGet();
minRt = Math.min(minRt, rtMs);
maxRt = Math.max(maxRt, rtMs);
if (sample.incrementAndGet() % 100 == 0) { // 每 100 次采样调整一次
// RT 翻倍说明排队严重,容量砍半;否则小幅上调
double adjust = maxRt > minRt * 2 ? 0.5 : 1.05;
limit = Math.max(50, Math.min(10000, limit * adjust));
log.info("自适应阈值调整 limit={} minRt={} maxRt={}", limit, minRt, maxRt);
}
}
}
生产实现还要加平滑(滑动平均)、滞回(上调慢、下调快)与最小样本数限制。
五、常见追问
Q1:自适应限流会不会抖动? 会。指标本身有噪声,按瞬时值直接调整会导致阈值震荡。工程上用滑动平均、限制调整步长、上调慢下调快来抑制。
Q2:和自动扩缩容什么关系? 自适应限流保护现有容量,扩缩容增加容量。限流先扛住,扩容跟上后再放开阈值,二者联动,否则扩容期间会被限流误伤。
Q3:怎么验证自适应有效? 压测时人为注入慢查询或降低下游能力,观察系统是否在 RT 上升后自动降低吞吐而不崩溃,同时看限流触发次数与业务成功率的变化。
Q4:Little's Law 怎么用?
并发数 = QPS × RT。已知线程池上限是 500、RT 是 100 ms,则理论 QPS 上限为 5000;RT 涨到 200 ms,上限自动降到 2500。
小结
- 自适应限流把固定阈值换成按实时指标计算的阈值,用来应对容量漂移。
- 两条主线:基于负载(CPU、load)与基于时延(Little's Law、BBR)。
- 必须抑制抖动:平滑、限制步长、上调慢下调快。