花都网站建设哪家好,长沙市旅游景点,免费的网络推广平台,建设通网站怎么投诉令牌桶算法
令牌桶是按照固定速率往桶中添加令牌#xff0c;请求是否被处理需要看桶中令牌是否足够#xff0c;当令牌数减为零时则拒绝新的请求#xff1b;漏桶则是按照常量固定速率流出请求#xff0c;流入请求速率任意#xff0c;当流入的请求数累积到漏桶容量时#…令牌桶算法
令牌桶是按照固定速率往桶中添加令牌请求是否被处理需要看桶中令牌是否足够当令牌数减为零时则拒绝新的请求漏桶则是按照常量固定速率流出请求流入请求速率任意当流入的请求数累积到漏桶容量时则新流入的请求被拒绝令牌桶限制的是平均流入速率允许突发请求只要有令牌就可以处理支持一次拿3个令牌4个令牌漏桶限制的是常量流出速率即流出速率是一个固定常量值比如都是1的速率流出而不能一次是1下次又是2从而平滑突发流入速率令牌桶允许一定程度的突发而漏桶主要目的是平滑流出速率
Guava RateLimiter
Guava的 RateLimiter提供了令牌桶算法实现平滑突发限流(SmoothBursty)和平滑预热限流(SmoothWarmingUp)实现。
平滑突发限流
使用 RateLimiter的静态方法创建一个限流器设置每秒放置的令牌数为5个。 返回的RateLimiter对象可以保证1秒内不会给超过5个令牌并且以固定速率进行放置达到平滑输出的效果。
public void testSmoothBursty() {RateLimiter r RateLimiter.create(5);while (true) {System.out.println(get 1 tokens: r.acquire() s);}/*** output: 基本上都是0.2s执行一次符合一秒发放5个令牌的设定。* get 1 tokens: 0.0s* get 1 tokens: 0.182014s* get 1 tokens: 0.188464s* get 1 tokens: 0.198072s* get 1 tokens: 0.196048s* get 1 tokens: 0.197538s* get 1 tokens: 0.196049s*/
}令牌累计
Guava RateLimiter的令牌积累数量是根据设定的速率和时间间隔来计算的。具体计算方式如下
首先RateLimiter会根据设定的速率每秒生成的令牌数量计算出令牌生成的时间间隔。 例如如果设定的速率是2个令牌/秒那么每个令牌生成的时间间隔是0.5秒1秒/2个令牌。当RateLimiter开始工作时它会记录当前时间并将令牌桶中的令牌数量初始化为0。当一个请求到达时RateLimiter会计算当前时间与上一次记录时间之间的时间间隔并根据设定的速率和时间间隔计算出应该生成的令牌数量。如果计算出的令牌数量小于等于令牌桶中的剩余令牌数量请求将被允许通过并且令牌桶中的令牌数量减少。如果计算出的令牌数量大于令牌桶中的剩余令牌数量请求将被限制或延迟处理直到令牌桶中有足够的令牌可用。 总结来说Guava RateLimiter根据设定的速率和时间间隔来计算应该生成的令牌数量并根据令牌桶中的剩余令牌数量来决定请求是否被允许通过。
public void testSmoothBursty2() {// RateLimiter使用令牌桶算法会进行令牌的累积如果获取令牌的频率比较低则不会导致等待直接获取令牌。RateLimiter r RateLimiter.create(2);while (true) {try {Thread.sleep(3000);} catch (Exception e) {}System.out.println(get 1 tokens: r.acquire(1) s);System.out.println(get 1 tokens: r.acquire(1) s);System.out.println(get 1 tokens: r.acquire(1) s);System.out.println(get 1 tokens: r.acquire(1) s);System.out.println(end);/*** output:get 1 tokens: 0.0sget 1 tokens: 0.0sget 1 tokens: 0.0sget 1 tokens: 0.499147sendget 1 tokens: 0.0sget 1 tokens: 0.0sget 1 tokens: 0.0sget 1 tokens: 0.499904s*/}
}在上面的代码中令牌桶中最多只能积累2个令牌是由于创建RateLimiter时指定的速率为2。RateLimiter.create(2)表示每秒生成2个令牌。令牌桶的大小取决于速率和时间间隔之间的关系。在这种情况下速率为2个令牌/秒意味着每秒生成2个令牌放入令牌桶中。 根据令牌桶算法令牌桶的大小可以理解为令牌桶的容量即最多可以容纳的令牌数量。在这里令牌桶的容量为2也就是最多可以积累2个令牌。 如果在某个时间点上令牌桶中已经有2个令牌而没有请求来消耗这些令牌那么令牌桶中不会继续积累更多的令牌。新的令牌只有在之前的令牌被消耗后才会生成并放入令牌桶中。 因此根据上述代码和速率设置令牌桶中最多只能积累2个令牌。 平滑预热限流
RateLimiter的 SmoothWarmingUp是带有预热期的平滑限流它启动后会有一段预热期逐步将分发频率提升到配置的速率。 比如下面代码中的例子创建一个平均分发令牌速率为2预热期为3分钟。由于设置了预热时间是3秒令牌桶一开始并不会0.5秒发一个令牌而是形成一个平滑线性下降的坡度频率越来越高在3秒钟之内达到原本设置的频率以后就以固定的频率输出。这种功能适合系统刚启动需要一点时间来“热身”的场景。
public void testSmoothwarmingUp() {RateLimiter r RateLimiter.create(2, 3, TimeUnit.SECONDS);while (true){System.out.println(get 1 tokens: r.acquire(1) s);System.out.println(get 1 tokens: r.acquire(1) s);System.out.println(get 1 tokens: r.acquire(1) s);System.out.println(get 1 tokens: r.acquire(1) s);System.out.println(end);/*** output:* get 1 tokens: 0.0s* get 1 tokens: 1.329289s* get 1 tokens: 0.994375s* get 1 tokens: 0.662888s 上边三次获取的时间相加正好为3秒* end* get 1 tokens: 0.49764s 正常速率0.5秒一个令牌* get 1 tokens: 0.497828s* get 1 tokens: 0.49449s* get 1 tokens: 0.497522s*/}
}在平滑预热限流的情况下令牌是不会积累的。 RateLimiter.create(2, 3, TimeUnit.SECONDS); 参数1每秒产生2个令牌参数2/3在前3秒内产生3个令牌且从慢到快如果RateLimiter.create(2, 4, TimeUnit.SECONDS); 代表在前4秒内产生4个令牌且从慢到快 核心函数说明
函数说明示例public static RateLimiter create(double permitsPerSecond)每秒产生permitsPerSecond个令牌RateLimiter.create(2)public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit)每秒产生permitsPerSecond个令牌在前warmupPeriod单位时间内产生warmupPeriod个令牌从慢到快RateLimiter.create(2, 3, TimeUnit.SECONDS)public double acquire(int permits)取得指定数量的令牌并返回等待时间limiter.acquire(1)public boolean tryAcquire(int permits)尝试取得指定数量的令牌返回成功或失败limiter.tryAcquire(1)public boolean tryAcquire(Duration timeout)尝试取得1个令牌并等待指定的时间返回成功或失败limiter.tryAcquire(Duration.ofSeconds(1))public boolean tryAcquire(int permits, long timeout, TimeUnit unit)尝试取得指定数量的令牌并等待指定的时间返回成功或失败limiter.tryAcquire(2, 10, TimeUnit.SECONDS)
参考
https://zhuanlan.zhihu.com/p/60979444