guava限流源码解读
核心变量
- startTick 参考点(限流初始化时间点)
- nowMicros 当前时间点(当前时间-参考点)
- stableIntervalMicros 生成令牌的速率(每微秒生成令牌数)
- maxPermits 可生成的最大令牌数
- storedPermits 令牌桶计数器
- nextFreeTicketMicros 下次可生成令牌的时间点(可生成令牌的时间点-参考点)
- timeoutMicros 获取令牌等待超时时间
核心方法
创建时间计数器
public static final SleepingStopwatch createFromSystemTimer() {
return new SleepingStopwatch() {
final Stopwatch stopwatch = Stopwatch.createStarted();
@Override
//获取当前时间基于参考点
protected long readMicros() {
return stopwatch.elapsed(MICROSECONDS);
}
@Override
protected void sleepMicrosUninterruptibly(long micros) {
if (micros > 0) {
Uninterruptibles.sleepUninterruptibly(micros, MICROSECONDS);
}
}
};
}
public static Stopwatch createStarted() {
return new Stopwatch().start();
}
//标记参考点
public Stopwatch start() {
checkState(!isRunning, "This stopwatch is already running.");
isRunning = true;
startTick = ticker.read();
return this;
}
public long elapsed(TimeUnit desiredUnit) {
return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
}
private long elapsedNanos() {
return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;
}
初始化SmoothBursty限流
static RateLimiter create(double permitsPerSecond, SleepingStopwatch stopwatch) {
RateLimiter rateLimiter = new SmoothBursty(stopwatch, 1.0 /* maxBurstSeconds */);
rateLimiter.setRate(permitsPerSecond);
return rateLimiter;
}
final void doSetRate(double permitsPerSecond, long nowMicros) {
//初始化令牌桶及下次获取令牌的时间
resync(nowMicros);
//计算令牌生成的速率
double stableIntervalMicros = SECONDS.toMicros(1L) / permitsPerSecond;
this.stableIntervalMicros = stableIntervalMicros;
doSetRate(permitsPerSecond, stableIntervalMicros);
}
void resync(long nowMicros) {
// if nextFreeTicket is in the past, resync to now
if (nowMicros > nextFreeTicketMicros) {
double newPermits = (nowMicros - nextFreeTicketMicros) / coolDownIntervalMicros();
storedPermits = min(maxPermits, storedPermits + newPermits);
nextFreeTicketMicros = nowMicros;
}
@Override
void doSetRate(double permitsPerSecond, double stableIntervalMicros) {
double oldMaxPermits = this.maxPermits;
//设置令牌桶容量
maxPermits = maxBurstSeconds * permitsPerSecond;
if (oldMaxPermits == Double.POSITIVE_INFINITY) {
// if we don't special-case this, we would get storedPermits == NaN, below
storedPermits = maxPermits;
} else {
//设置令牌桶存储,令牌桶容量变更后对应比例换算
storedPermits =
(oldMaxPermits == 0.0)
? 0.0 // initial state
: storedPermits * maxPermits / oldMaxPermits;
}
}
获取令牌
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();
//判断当前时间点是否可以获取令牌
if (!canAcquire(nowMicros, timeoutMicros)) {
return false;
} else {
//获取令牌并计算超时等待时间
microsToWait = reserveAndGetWaitLength(permits, nowMicros);
}
}
//超时阻塞等待
stopwatch.sleepMicrosUninterruptibly(microsToWait);
return true;
}
//判断下次获取令牌的时间是否超过当前时间+超时时间
private boolean canAcquire(long nowMicros, long timeoutMicros) {
return queryEarliestAvailable(nowMicros) - timeoutMicros <= nowMicros;
}
@Override
final long queryEarliestAvailable(long nowMicros) {
return nextFreeTicketMicros;
}
@Override
final long reserveEarliestAvailable(int requiredPermits, long nowMicros) {
resync(nowMicros);
long returnValue = nextFreeTicketMicros;
//令牌桶内令牌
double storedPermitsToSpend = min(requiredPermits, this.storedPermits);
//超出令牌桶以外超时部分令牌
double freshPermits = requiredPermits - storedPermitsToSpend;
//超时等待时间
long waitMicros =
storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
+ (long) (freshPermits * stableIntervalMicros);
//计算出下次获取令牌的时间
this.nextFreeTicketMicros = LongMath.saturatedAdd(nextFreeTicketMicros, waitMicros);
//扣除令牌
this.storedPermits -= storedPermitsToSpend;
return returnValue;
}
注意事项
timeoutMicros 不易设置过大,会阻塞用户线程