resilience4j-timelimiter 1.7.1 解读

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;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值