|
|
51CTO旗下网站
|
|
移动端

Sentinel中的冷启动限流算法

令牌桶算法的原理是:按一定的速率往令牌桶中放入令牌,当接收到请求时,从令牌桶申请令牌,只有拿到令牌的请求才能通过。当令牌桶放满时,多余的令牌就会被丢弃;当令牌桶为空时,请求拿不到令牌就拒绝请求。

作者:wujiuye 来源:Java艺术|2020-08-03 08:04

 

冷启动算法基于令牌桶算法实现。

令牌桶算法的原理是:按一定的速率往令牌桶中放入令牌,当接收到请求时,从令牌桶申请令牌,只有拿到令牌的请求才能通过。当令牌桶放满时,多余的令牌就会被丢弃;当令牌桶为空时,请求拿不到令牌就拒绝请求。

例如,想要使用令牌桶算法限制接口的最大QPS为200,那么就要每5毫秒就要生产一个令牌放入令牌桶,且生产令牌放入的速度不变。

冷启动算法用于控制令牌桶的令牌生产速率,即控制每个令牌生产的时间间隔。

假设冷启动时长为10秒,初始状态为冷启动状态,限流阈值为200QPS,正常情况下生产令牌的速率应该为5毫秒/个,而在冷启动阶段,速率会从最小值上升至5毫秒/个,最小速率与冷启动系数有关,与冷启动周期时长有关。

Sentinel与Guava的实现不同,Sentinel可能是出于对性能的考虑,并不控制每个请求的通过时间间隔,只控制每秒钟能通过的请求数。

通过下面这张图来理解冷启动算法。

坐标轴:

  • 横坐标storedPermits代表存储桶中的令牌数量;
  • 纵坐标代表获取一个令牌需要的时间,即请求通过的时间间隔;

stableInterval:稳定产生令牌的时间间隔,假设限流阈值QPS为200,stableInterval的值为5毫秒。

coldInterval:冷启动产生令牌的最大时间隔间,等于稳定产生令牌的时间间隔乘以冷启动系数(stableInterval * coldFactor),Sentinel中coldFactor默认为3。

warmupPeriod:预热时间,即冷启动周期,对应上图中的梯形面积,Sentinel中默认为10秒。

thresholdPermits:从冷启动到正常的令牌桶中令牌数量的阈值,当令牌桶中的令牌数量超过该值时,则进入冷启动阶段。

由于coldFactor默认为3,所以(coldInterval - stableInterval)是stableInterval的两倍,所以从thresholdPermits到0的时间是从maxPermits到thresholdPermits时间的一半,也就是冷启动周期的一半。因为梯形的面积等于warmupPeriod,所以长方形面积是梯形面积的一半,长方形的面积是warmupPeriod / 2。

根据长方形面积公式:长 * 宽 = 面积

可得:

  1. thresholdPermits = 0.5 * warmupPeriod / stableInterval 

maxPermits:最大允许桶中存放的令牌数。

根据梯形的面积公式:(上低 + 下低)* 高 / 2

可得:

  1. warmupPeriod = (stableInterval + coldInterval)* (maxPermits - thresholdPermits)/ 2 

推出:

  1. maxPermits = thresholdPermits + 2 * warmupPeriod / (stableInterval + coldInterval) 

slope:直线的斜率,即生产令牌的速率。

根据斜率计算公式:(y2-y1) / (x2-x1),可得:

  1. slope = (coldInterval - stableInterval) / (maxPermits - thresholdPermits) 

Sentinel每秒生产一次令牌,将新生产的令牌放入令牌桶,并记录本次生产令牌的时间,当下次生产时,根据当前时间与上一次生产令牌的时间间隔计算、以及每个令牌的生产间隔时间计算出本次需要生产的令牌数。

服务第一次启动时,或者接口很久没有被访问,都会导致当前时间与上次生产令牌的时间相差甚远,所以第一次生产令牌将会生产maxPermits个令牌,直接将令牌桶装满。由于令牌桶已满,接下来10s就是冷启动阶段。

由于冷启动阶段生产令牌的间隔时间比较正常消费速度慢,因此随着时间的推移,桶中的剩余令牌数就会趋近于thresholdPermits,生产令牌的时间间隔也会从coldInterval降低到stableInterval。当桶中剩余令牌数小于thresholdPermits时,冷启动结束,系统进入稳定状态,生产令牌的时间间隔为stableInterval,每秒生产的令牌数就等于QPS。

Sentinel并不会在请求通过时减少令牌桶中的令牌数量,而是在下一秒生产新的令牌时,再减去桶中与上一秒通过的请求数相等数量的令牌,这就是Sentinel官方介绍的令牌自动掉落。

Sentinel没有在每个请求通过时从令牌桶取走令牌,那么Sentinel是如何控制QPS的呢,我们再来看一张图:

x1:当前令牌桶中超过thresholdPermits的令牌数量;

y1:y1加上stableInterval等于当前令牌生产的时间间隔;

根据斜率和x1可算出y1:

  1. y1 = slope * x1 

y1加上stableInterval即为当前的令牌生产速率。

当前秒生产令牌的时间间隔为:

  1. slope * (storedTokens - thresholdPermits) + stableInterval 

由于:stableInterval = 1.0(1秒) / 限流阈值(count)

所以上述等式 = slope * (storedTokens - thresholdPermits) + 1.0 / count

最后算得当前时间戳的QPS阈值为:

  1. 1.0 / slope * (storedTokens - thresholdPermits) + 1.0 / count 

参考文献:

[1] Guava RateLimiter分析:

https://blog.wangqi.love/articles/Java/Guava%20RateLimiter%E5%88%86%E6%9E%90.html

本文转载自微信公众号「Java艺术」,可以通过以下二维码关注。转载本文请联系Java艺术公众号。

【编辑推荐】

  1. 对标Eureka的AP一致性,Nacos如何实现Raft算法
  2. Paxos、Raft不是一致性算法/协议?
  3. 浅谈TCP/IP传输层TCP BBR算法
  4. 【高并发】如何实现亿级流量下的分布式限流?这些理论你必须掌握!!
【责任编辑:武晓燕 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

大数据安全运维实战

大数据安全运维实战

CDH+Ambari
共20章 | 大数据陈浩

91人订阅学习

实操案例:Jenkins持续交付和持续部署

实操案例:Jenkins持续交付和持续部署

微服务架构下的自动化部署
共18章 | freshman411

186人订阅学习

思科交换网络安全指南

思科交换网络安全指南

安全才能无忧
共5章 | 思科小牛

110人订阅学习

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO官微