前言: 本文简要说明了限流相关基础点,重点阐述guava 的平滑预热限流(SmoothWarmingUp) 源码核心要点
一 限流目的
大数据量高并发微服务系统中,限流是技术手段之一。限流的目的是保护服务节点或集群底层的存储资源,防止调用方过度使用服务,引起系统崩溃,或某个调用方过度使用服务,影响其他调用方。
二 限流粒度
1. 单节点/分布式
1) guava ratelimiter
2) redis + lua
2. 服务级/方法级
三 限流规则
何时执行限流受制于服务本身的处理能力,以及下游服务或底层存储等多方面约束。
1. 配置固定值
2. 依据单点服务的总体LOAD,QPS和线程数等数据设定触发规则
四 限流响应
1. 服务端立即返回错误,由客户端执行兜底操作
2. 服务端设定超时阈值,超时后,由客户端降级
3. 服务端直接降级
五 限流算法
常见的限流算法有: 计数器,令牌桶,漏桶。
六 限流实现
Guava的RateLimiter源码分析

RateLimiter用静态方法创建限流器: 平滑突发限流(SmoothBursty) 和 平滑预热限流(SmoothWarmingUp)。
RateLimiter用Stopwatch来计算经过的时间(精确到纳秒),比调用System.nanoTime()性能更佳,表达形式更丰富。
RateLimiter可以预先透支令牌,支持流量突发,为实现流量突发,设计了核心变量nextFreeTicketMicros(下一次请求可以获取令牌的起始时间)。另外,每次请求令牌时,会同步更新令牌桶及nextFreeTicketMicros(resync方法),节约了线程资源。
1. SmoothBursty

如上图,假设QPS为1,每一格为1秒,流程简述:
1) R1,获取 1个令牌,nextFreeTicketMicros为0,允许请求通过,无令牌,透支一个,nextFreeTicketMicros赋值为N1
2) R2,获取1个令牌,由于nextFreeTicketMicros为N1,R2需要等待到N1时刻。生成R2的令牌需要1秒钟,nextFreeTicketMicros赋值为N2
3) R3,获取3个令牌,N2到N8无请求,会囤积一个令牌,R3用掉此令牌,还需透支2个,nextFreeTicketMicros最终赋值为N10,R3通过
2. SmoothWarmingUp

说明:
1)坐标:
横坐标为令牌桶存储的令牌数,阈值为thresholdPermits(t),最大值为maxPermits(m)
纵坐标为发放令牌的速度,稳定值stableInterval(s) , 预热冷却值coldInterval(c)
2)变量:
stableInterval (s) 发放令牌的速度,即生产一个令牌所需时间
coldInterval (c) 冷却时发放令牌的速度:c =3 * s
thresholdPermits(t) 存储的令牌数阈值
maxPermits(m) 存储的最大令牌数
warmUpPeriod(W2) 预热的时间长度
3)其他:
从thresholdPermits 到maxPermits存在固定的斜率
从thresholdPermits到0所需时间等于warmupPeriod/2
从maxPermits到thresholdPermits所需时间(warmupPeriod)等于梯形区域面积
如上说明,
疑问1: 为什么coldFactor 设定为3倍s ?
疑问2: 为什么从thresholdPermits到0所需时间等于warmupPeriod/2(图中矩形面积是梯形面积的1/2)?
1) 可理解为这些假定是任意的,也为简化整体预热流程。
2) 通过积分计算过程,解释上述疑问
平行线方程
斜线方程 ,
预热整个过程的耗时为0 到m的积分, 其中,
0到t 的定积分
即
t 到m的定积分
即
若设定coldFactor为3倍s, 则 W2 = 2s(m - t), 再设定W2 = 2st, 则 m = 2t
疑问3: 为什么从maxPermits到thresholdPermits所需时间(warmupPeriod)等于梯形区域面积?
定积分的几何意义即是曲线(斜线)与横坐标围成的区域面积。
[完]