基于令牌桶算法的限流器RateLimiter分析

主要从以下几个方面进行分析

RateLimiter工作原理的总体介绍

首先RateLimiter是goole 出品的一个基于令牌桶算法的一个组件,其中有两种模式(XSmoothBursty和XSmoothWarmingUp),XSmoothBursty是以恒定速率生成令牌,也就是平滑模式,比如1秒生成5个令牌,那么就是200微秒产生一个令牌。而SmoothWarmingUp代表渐进模式,当速率变大到一定程度后趋于平衡,该模式可以应对突发流量的情况发生。
RateLimiter支持提前消费的概念,比如我每次只能挣5块钱,但是我买东西要花费6块钱,那怎么办呢,我可以通过向老板预支11块钱钱去购买东西,那下一次我还是要买6块钱的东西,那我就得等把上一次的1块钱先还掉才能进行下一次发工资,而挣这一块钱所花费的时间+本身挣5块钱所花费的时间就是我等待的时间,具体数据后面会通过大量的测试进行验证,包括其他情况。

RateLimiter的继承关系(基类与子类的关系图)

SmoothWarmingUp->SmoothRateLimiter->RateLimiter关系图
SmoothBursty->SmoothRateLimiter->RateLimiter关系图

RateLimiter是一个抽象类,目前只有一个子类SmoothRateLimiter,而SmoothRateLimiter也是一个抽象类,在SmoothRateLimiter下有两个实现子类,一个是SmoothBursty,一个是SmoothWarmingUp。

关键属性字段分析

RateLimiter中的字段解析

stopwatch时间计算器,这里采用的微秒计时,后面用来计算还有多长时间获取令牌时用
mutexDoNotUseDirectly对象锁,设置速率时,线程安全保护,避免临界资源竞争,此处采用的双重锁检查的单列模式来生成的锁

SmoothRateLimiter中的字段解析

storedPermits剩余的令牌数
maxPermits表示最大允许的令牌数
stableIntervalMicros每隔多长时间产生一个令牌,采用的时间是微秒
nextFreeTicketMicros表示下一次可以获取令牌的时间,此处是一个相对时间

SmoothBursty中的字段分析

·maxBurstSeconds表示如果你很久没有请求,但是令牌数不会随着时间推移而增加,而是只缓存1秒的时间的令牌

SmoothWarmingUp中的字段分析

warmupPeriodMicros
slope
thresholdPermits
coldFactor

核心方法分析(创建—>申请)

SmoothBursty模式创建RateLimiter的过程(时序图)

在这里插入图片描述

  1. 在RateLimiter这个抽象类中有创建RateLimiter对象的两个静态方法create(),根据不同的入参获取到具有相应模式的RateLimiter对象,比如创建一个SmoothBursty模式并每秒产生2个令牌的RateLimiter限流器。
//入参必须是大于0的数,不然会抛rate must be positive 异常
RateLimiter rateLimiter = RateLimiter.create(2);
  1. 进入create方法中,我们发现,做了两件事,第一件事:通过内部类SmoothBursty实例化了一个RateLimiter限流器,入参为:stopwatch(计时器对象)和maxBurstSeconds(最大缓存秒数)第二件事: 设置生成令牌的速率的setRate方法。
static XRateLimiter create(double permitsPerSecond, XRateLimiter.SleepingStopwatch stopwatch) {
        XRateLimiter rateLimiter = new XSmoothRateLimiter.XSmoothBursty(stopwatch, 1.0 /* maxBurstSeconds */);
        System.out.println("permitsPerSecond:"+permitsPerSecond);
        //创建限流器的时候,进行获取令牌的速度设置, 此次有点类似于信号量
        rateLimiter.setRate(permitsPerSecond);
        return rateLimiter;
    }
  1. 进入setRate方法进行速率设置,在这个方法中,通过锁机制进入doSetRate方法…先调用resync方法进行初始的数据计算,比如:当此刻计时器的数据大于下一次获取令牌的时间(此刻时间为0)的情况下,开始计算storedPermitsd的值和nextFreeTicketMicros的值。
void resync(long nowMicros) {
        if (nowMicros > nextFreeTicketMicros) {
            double newPermits = (nowMicros - nextFreeTicketMicros) / coolDownIntervalMicros();
            storedPermits = min(maxPermits, storedPermits + newPermits);
            nextFreeTicketMicros = nowMicros;
        }
    }
  1. 接下来设置stableIntervalMicros的值(也就是每多少时间产生一个令牌),并设置最大令牌数maxPermits的值,以及更新storedPermits的值。
            //计算出旧的最大许可存储量
            double oldMaxPermits = this.maxPermits;
            //获取新的最大的许可存储量(按照秒计算)
            maxPermits = maxBurstSeconds * permitsPerSecond;
            //如果旧的最大许可为无限大的情况,那么没有被使用的许可数量也是无限多
            if (oldMaxPermits == Double.POSITIVE_INFINITY) {
                storedPermits = maxPermits;
                //如果不是无限多的话,就重新计算还有多少个许可令牌数
            } else {
                storedPermits = (oldMaxPermits == 0.0)? 0.0 : storedPermits * maxPermits / oldMaxPermits;
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值