springcloud的网关(五)--基于redis实现分布式令牌桶的限流

一:单机式令牌桶的缺陷

  在上述的记账中我们讨论使用了Bucket来做限流机制。

  /**
     * 创建一个令牌桶
     * @return
     */
    private Bucket createNewBucket() {   	
    	
        Refill refill = Refill.of(1, Duration.ofSeconds(1000));//  1:每次补充令牌的数量  ;   2 补充token的时间间隔
        Bandwidth limit = Bandwidth.classic(10, refill); 	//10,通最多能装10个令牌
        return Bucket4j.builder().addLimit(limit).build();
    }

   我们来进一步查看其中的代码实现

    public LocalBucket build() {
        BucketConfiguration configuration = buildConfiguration();
        switch (synchronizationStrategy) {
            case LOCK_FREE: return new LockFreeBucket(configuration, timeMeter);
            case SYNCHRONIZED: return new SynchronizedBucket(configuration, timeMeter);
            case NONE: return new SynchronizedBucket(configuration, timeMeter, FakeLock.INSTANCE);
            default: throw new IllegalStateException();
        }
    }

   这是bucket4j最后使用Build()方法实现的本地的localBucket。事实上,只能在本机上实现,一旦分布则数据不同意。

 

二:分布式限领令牌桶的可行性讨论

   我们还是来说一下限流的机制: 当访问开始消耗桶中的令牌达到最大值,则桶为空报错,期间桶中令牌还按照一定的时间规律

补充。                               

   那么,令牌桶的核心就是3个概念:桶中最大的令牌数,桶补充令牌的时间间隔,桶每次补充令牌的个数。

我们来思考:

  (1)令牌桶核心 业务就是:消耗令牌数和新增令牌数。如果我们使用定时任务来添加令牌。比如根据ip限流。

  

                  其中实线为定时添加令牌,虚线为访问消耗的令牌。但是这样做的消费太高,一个ip就要创建一个定时任务。

  (2)简化版令牌桶:如每10s只允许一个ip访问20次。

             实现思路:使用redis的失效时间。即:a拿着ip去访问redis中该ip对应的次数,当次数不为0,则可以访问。当该ip的缓存

                                 达到失效时间,该ip去redis中发现为null,则重新初始化redis。

                       这样操作,我们不需要管,每一次补充多少,即在一定时间间隔内,访问次数是固定的。缺点没有动态补充。

      

     (3)令牌桶的实现:此方法思路是在(2)的基础上实现,只不过添加了动态补充。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值