RateLimiterConfig config = RateLimiterConfig.custom()
//当令牌不够时,等待1秒钟,若1秒钟后得不到则抛出异常RequestNotPermitted
.timeoutDuration(Duration.ofSeconds(1))
//5秒钟一次重置令牌到limitForPeriod,若时间被回拨,回拨时间点周期有所影响
.limitRefreshPeriod(Duration.ofSeconds(5))
//每次令牌数
.limitForPeriod(1).build();
RateLimiterRegistry register = RateLimiterRegistry.of(config);
RateLimiter user = register.rateLimiter("user");
for (int i = 0; i < 60; i++) {
//使用内置的包装器执行调用,内部完成令牌的申请及消耗等等。 若请求的令牌不够,则会发生阻塞,直到
//得到令牌或者超时
user.executeRunnable(()->{
System.out.println(System.currentTimeMillis()/1000);
});
}
user.executeRunnable
static CheckedRunnable decorateCheckedRunnable(RateLimiter rateLimiter, int permits, CheckedRunnable runnable) {
return () -> {
//获取令牌,若令牌不够,会进行等待或者达到超时时间抛出异常
waitForPermission(rateLimiter, permits);
try {
//令牌获取成功,允许执行
runnable.run();
rateLimiter.onSuccess();
} catch (Exception exception) {
//执行业务逻辑报错
rateLimiter.onError(exception);
throw exception;
}
};
}
rateLimiter.acquirePermission(permits);
static void waitForPermission(final RateLimiter rateLimiter, int permits) {
boolean permission = rateLimiter.acquirePermission(permits);
if (Thread.currentThread().isInterrupted()) {
throw new AcquirePermissionCancelledException();
}
if (!permission) {
throw RequestNotPermitted.createRequestNotPermitted(rateLimiter);
}
}
rateLimiter.acquirePermission(permits);
@Override
public boolean acquirePermission(final int permits) {
long timeoutInNanos = state.get().config.getTimeoutDuration().toNanos();
State modifiedState = updateStateWithBackOff(permits, timeoutInNanos);
boolean result = waitForPermissionIfNecessary(timeoutInNanos, modifiedState.nanosToWait);
publishRateLimiterAcquisitionEvent(result, permits);
return result;
}
updateStateWithBackOff(permits, timeoutInNanos);
next = calculateNextState(permits, timeoutInNanos, prev);
//permits 需要多少令牌
//timeoutInNanos 最多能够等待多久
//activeState 当前状态
private State calculateNextState(final int permits, final long timeoutInNanos,
final State activeState) {
//循环刷新令牌周期(纳秒) 比如1秒钟刷新一次
long cyclePeriodInNanos = activeState.config.getLimitRefreshPeriod().toNanos();
//一次刷新周期的令牌数量
int permissionsPerCycle = activeState.config.getLimitForPeriod();
//当前时间纳秒
long currentNanos = currentNanoTime();
//当前应该是第几次刷新
long currentCycle = currentNanos / cyclePeriodInNanos;
//上一次是第几次刷新
long nextCycle = activeState.activeCycle;
//上一次剩余令牌数量,
int nextPermissions = activeState.activePermissions;
if (nextCycle != currentCycle) {
//当前刷新周期和上一次刷新周期不等,说明可以进行一次刷新了
//此次刷新周期和上一次周期的间隔周期数,这里使用的是System.nanoTime 不怕时间调整的问题
long elapsedCycles = currentCycle - nextCycle;
//计算在间隔周期时间内,总共应该产生多少令牌
long accumulatedPermissions = elapsedCycles * permissionsPerCycle;
//此次周期设置到下次周期
nextCycle = currentCycle;
//将此次剩余的令牌数量+周期间隔应该增长的令牌数量 与 一次周期令牌数量比较去最小值。这里
//(令牌数量+周期间隔应该增长的令牌数量应该永远大于permissionsPerCycle,除非jvm运行很久,导致System.nanoTime归零。
//使得accumulatedPermissions为负数)
nextPermissions = (int) min(nextPermissions + accumulatedPermissions,
permissionsPerCycle);
}
//nextPermissions 记录了当前令牌数量
//计算此次令牌获取需要等待多久时间
long nextNanosToWait = nanosToWaitForPermission(
permits, cyclePeriodInNanos, permissionsPerCycle, nextPermissions, currentNanos,
currentCycle
);
//构建下一个状态
State nextState = reservePermissions(activeState.config, permits, timeoutInNanos, nextCycle,
nextPermissions, nextNanosToWait);
return nextState;
}
private long nanosToWaitForPermission(final int permits, final long cyclePeriodInNanos,
final int permissionsPerCycle,
final int availablePermissions, final long currentNanos, final long currentCycle)
//permits 需要多少令牌
//cyclePeriodInNanos 循环刷新令牌周期(纳秒) 比如1秒钟刷新一次
//permissionsPerCycle 一次刷新周期的令牌数量
//availablePermissions 记录了当前令牌数量
//currentNanos 当前时间纳秒
//currentCycle 当前循环周期
private long nanosToWaitForPermission(final int permits, final long cyclePeriodInNanos,
final int permissionsPerCycle,
final int availablePermissions, final long currentNanos, final long currentCycle) {
if (availablePermissions >= permits) {
//令牌足够使用,无需等待
return 0L;
}
//计算下一次令牌发放时间
long nextCycleTimeInNanos = (currentCycle + 1) * cyclePeriodInNanos;
//与当前时间相比,距离下一次令牌发放还有多少时间
long nanosToNextCycle = nextCycleTimeInNanos - currentNanos;
//此次可用令牌数量+下一个周期下发的令牌数量
int permissionsAtTheStartOfNextCycle = availablePermissions + permissionsPerCycle;
//permissionsAtTheStartOfNextCycle - permits 到下一个周期后,除开本次的申请,还有多少令牌可以留给其它用,可能为负值,
//负值说明不够,还需要使用后面的周期令牌。通过这里计算需要使用后续多少周期。
// permissionsAtTheStartOfNextCycle - permits 不可能大于permissionsPerCycle
// 1、permissionsAtTheStartOfNextCycle - permits >=0 则fullCyclesToWait=0.
// 2、permissionsAtTheStartOfNextCycle - permits < 0 则fullCyclesToWait表示需要继续向下借用多少周期
int fullCyclesToWait = divCeil(-(permissionsAtTheStartOfNextCycle - permits), permissionsPerCycle);
//当前时间+下次周期时间+借用后续周期时间总和表示需要等待的周期
return (fullCyclesToWait * cyclePeriodInNanos) + nanosToNextCycle;
}
//permits 申请令牌数
//timeoutInNanos 最多能够等待多久
//cycle 此次令牌刷新周期
//permissions 令牌数量
//nanosToWait 需要等待多久
private State reservePermissions(final RateLimiterConfig config, final int permits,
final long timeoutInNanos,
final long cycle, final int permissions, final long nanosToWait) {
//判断是否执行等待,若需要等待时间超过了允许等待时间,则不允许执行等待,进行报错处理
boolean canAcquireInTime = timeoutInNanos >= nanosToWait;
int permissionsWithReservation = permissions;
if (canAcquireInTime) {
//如果允许等待,则扣减相应的令牌数量
permissionsWithReservation -= permits;
}
//构建新的状态
return new State(config, cycle, permissionsWithReservation, nanosToWait);
}
//timeoutInNanos 最大允许等待时间
//nanosToWait 实际需要等待时间
private boolean waitForPermissionIfNecessary(final long timeoutInNanos,
final long nanosToWait) {
//无需等待
boolean canAcquireImmediately = nanosToWait <= 0;
//需要等待
boolean canAcquireInTime = timeoutInNanos >= nanosToWait;
if (canAcquireImmediately) {
//无需等待
return true;
}
if (canAcquireInTime) {
//需要等待
return waitForPermission(nanosToWait);
}
//申请的资源无法通过扩展周期进行满足。所以等待一个等待期后拒绝,返回false
waitForPermission(timeoutInNanos);
return false;
}