RateLimiter - YUHAO-ZX/StudyCollection GitHub Wiki
google RateLimiter 解读
1.使用
RateLimiter r = RateLimiter.create(10);
for(int i=0;i<10;i++){
if(!r.tryAcquire()){
//TODO 被限流
return ;
}
//TODO 业务代码
}
2.源码:tryAcquire()
public boolean tryAcquire(int permits, long timeout, TimeUnit unit) {
long timeoutMicros = max(unit.toMicros(timeout), 0);//获取超时
checkPermits(permits);//参数检测
long microsToWait;
synchronized (mutex()) {//锁
long nowMicros = stopwatch.readMicros();//读取stopwatch创建后到此刻的微秒数(1微秒=1/1000 毫秒)
if (!canAcquire(nowMicros, timeoutMicros)) {//判断是否被限流
return false;
} else {
microsToWait = reserveAndGetWaitLength(permits, nowMicros);//核心函数,处理限流逻辑
}
}
stopwatch.sleepMicrosUninterruptibly(microsToWait);
return true;
}
3.reserveAndGetWaitLengt()
private long reserveNextTicket(double requiredPermits, long nowMicros) {
resync(nowMicros);//!!更新令牌,限流时间
long microsToNextFreeTicket = nextFreeTicketMicros - nowMicros;
//计算此次调用能够获取的令牌数
double storedPermitsToSpend = Math.min(requiredPermits, this.storedPermits);
//计算还没有获取到的令牌数
double freshPermits = requiredPermits - storedPermitsToSpend;
//!!storedPermitsToWaitTime 返回0 , stableIntervalMicros 为 (1/限流数)*1000000
long waitMicros = storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
+ (long) (freshPermits * stableIntervalMicros);
//!!计算时间,在此时间之前不能再接收新的请求,请求将被被拒绝
this.nextFreeTicketMicros = nextFreeTicketMicros + waitMicros;
this.storedPermits -= storedPermitsToSpend;
return microsToNextFreeTicket;
}
4.resync()
private void resync(long nowMicros) {
// if nextFreeTicket is in the past, resync to now
//storedPermits 代表可用令牌数目,stableIntervalMicros 为 (1/限流数)*1000000
if (nowMicros > nextFreeTicketMicros) {
storedPermits = Math.min(maxPermits,
//计算可用令牌数:可用令牌+(两次请求间隔(秒)* 限流数)(相当于这段时间内均摊的可获取令牌数)
storedPermits + (nowMicros - nextFreeTicketMicros) / stableIntervalMicros);
nextFreeTicketMicros = nowMicros;//更新nextFreeTicketMicros 为当前时间
}
}
5.解读
从上面分析可以得出,底层会每隔:1/限流数(s) 放入一个令牌(并不是真正意义上的每秒限流多少次),然后外部请求去消费,可能存在高并发情况下先到的请求被挡掉。