令牌桶限流 - RateLimiter
2019-07-02 本文已影响0人
沐兮_d64c
1,RateLimiter类层次结构
1)SmoothRateLimiter平滑限流
image.png
2)SmoothBursty 平滑支持突发
image.png
3)SmoothWarmingUp 平滑预热限流
image.png
2,RateLimiter基类
1)成员计时器、锁
image.png
2)模板方法set、get速率
image.png
3,SmoothRateLimiter抽象类
1)令牌存储
image.png
nextFreeTicketMicros:下次请求需要等到nextFreeTicketMicros时刻才可以获取令牌。如果线程1与消费permits多,则nextFreeTicketMicros越往后。
2)resync控制方法
image.png
4,令牌生成与获取
1)令牌生成
image.png
定时任务生成令牌
:系统资源消耗极大,如跟对每个user限流,则需要开启n个定时任务。(不采取)
惰性结算生成令牌
:根据nowMicros > nextFreeTicketMicros作比较,如果大于说明不需要等待,补充nowMicros - nextFreeTicketMicros 之间生成的令牌。 如果小于,则需要等待。
2)令牌获取
acquire方法:计算获取permits个令牌需要等待的时间 ->底层调用Thread.sleep休眠 -> 返回waitTime休眠时间。
基于synchronized:实现同步
image.png
image.png
reserveEarliestAvailable模板方法,SmoothRateLimiter实现:计算下一次请求需要等待的时间,nextFreeTicketMicros。
增加storedPermits令牌:resync:增加从nowMicros - 原nextFreeTicketMicros之间可以产生的令牌数。
image.png
基于当前时间,更新storedPermits和nextFreeTicketMicros
image.png
5,SmoothBursty 平滑支持突发
1)创建
image.png
默认可以存储maxBurstSeconds秒未使用的permits,避免不必要的停顿。
创建SmoothBursty时,可以指定maxBurstSeconds,用于计算maxPermits。
2)类结构
image.png
3)SmoothBursty预消费(令牌不足下次调用来买单
)
如图令牌桶无令牌,第一次acquire未阻塞。第二次阻塞了3s,因为预先获取了3个permits,qps为1。
image.png
6,SmoothWarmingUp:平滑预热限流
1)创建
image.png
permitsPerSecond:每秒的令牌数
warmupPeriod:预热期(before reaching its stable (maximum) rate)
unit:预热期,时间单位
coldFactor:冷启动系数,默认3.0
cold interval:coldIntervalMicros = stableIntervalMicros * coldFactor;默认是stable interval的3倍。
image.png
2)thresholdPermits,系统 stable 阶段和 cold 阶段的临界点
slope代表梯形的斜率
image.png
3)平滑预热图(从右往左看
)
thresholdPermits是一个拐点。
当令牌数小于thresholdPermits时,生成令牌的间隔时间稳定在stable interval
当令牌数大于thresholdPermits时,生成令牌的间隔时间以一个固定的速率发生变化。
image.png
4)storedPermitsToWaitTime方法
SmoothBursty:storedPermitsToWaitTime方法,直接返回0。
SmoothWarmingUp:storedPermitsToWaitTime方法根据令牌数与thresholdPermits的关系来计算等待的时间。`
image.png
7,tryAcquire非阻塞式限流、降级
1)使用tryAcquire达到非阻塞式限流。
image.png
2)tryAcquire可以指定超时时间。
image.png