Sentinel中的冷启动限流算法

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

 [[336019]]

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

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

例如,想要使用令牌桶算法限制接口的最大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艺术公众号。

 

责任编辑:武晓燕 来源: Java艺术
相关推荐

2024-11-05 15:02:41

2024-10-16 20:31:25

2021-05-14 07:45:07

Sentinel 接口限流

2022-05-29 21:38:11

限流熔断流量

2022-05-09 07:35:48

动态集群限流

2021-05-21 08:30:26

Sentinel GateWay 微服务

2024-09-06 13:53:28

2021-03-16 08:31:59

微服务Sentinel雪崩效应

2020-09-08 06:48:07

微服务算法限流

2024-02-04 10:08:34

2023-04-26 09:16:17

2024-07-05 16:47:46

2019-06-20 17:39:12

Android启动优化

2024-06-05 10:07:00

限流微服务算法

2023-09-18 14:39:02

2022-05-03 19:38:15

限流微服务Sentinel

2021-11-04 10:11:02

Sentinel网关限流

2022-10-28 18:41:53

Java服务限流

2021-05-25 08:01:55

SentinelRedis 流控算法

2023-11-28 09:19:12

点赞
收藏

51CTO技术栈公众号