美文网首页
RateLimiter限流器使用

RateLimiter限流器使用

作者: leiwingqueen | 来源:发表于2018-11-04 17:34 被阅读0次

    一、概要说明

    最近在工作中涉及到类似抢购的业务,在请求并发量高的时候会阻塞到正常业务的访问。因此考虑使用guawa的rateLimiter进行限流,对超限的流量进行降级处理。保证正常的业务运行

    二、RateLimiter的特性

    RateLimiter使用令牌桶算法,相对于传统的根据每秒的请求数进行限流的方式,令牌桶算法会让流量更加平滑地流入。eg.QPS限制为100,假如这100个请求是在1ms内同时进来,也有可能让系统崩溃。

    三、核心源码分析

    /**
       * Acquires the given number of permits from this {@code RateLimiter}, blocking until the request
       * can be granted. Tells the amount of time slept, if any.
       *
       * @param permits the number of permits to acquire
       * @return time spent sleeping to enforce rate, in seconds; 0.0 if not rate-limited
       * @throws IllegalArgumentException if the requested number of permits is negative or zero
       * @since 16.0 (present in 13.0 with {@code void} return type})
       */
      @CanIgnoreReturnValue
      public double acquire(int permits) {
        long microsToWait = reserve(permits);
        stopwatch.sleepMicrosUninterruptibly(microsToWait);
        return 1.0 * microsToWait / SECONDS.toMicros(1L);
      }
    /**
       * Reserves the given number of permits from this {@code RateLimiter} for future use, returning
       * the number of microseconds until the reservation can be consumed.
       *
       * @return time in microseconds to wait until the resource can be acquired, never negative
       */
      final long reserve(int permits) {
        checkPermits(permits);
        synchronized (mutex()) {
          return reserveAndGetWaitLength(permits, stopwatch.readMicros());
        }
      }
    /**
       * Reserves next ticket and returns the wait time that the caller must wait for.
       *
       * @return the required wait time, never negative
       */
      final long reserveAndGetWaitLength(int permits, long nowMicros) {
        long momentAvailable = reserveEarliestAvailable(permits, nowMicros);
        return max(momentAvailable - nowMicros, 0);
      }
    
    @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;
      }
    

    我们重点关注reserveEarliestAvailable这个方法。
    storedPermits为令牌生成的数量,resync这个方法会根据当前的时间和上一次生成的令牌的时间对比,计算出本次生成的令牌数量。eg.QPS设置为100,上一次请求和当前时间相隔为2ms,则当前的令牌数量为20。

    相关文章

      网友评论

          本文标题:RateLimiter限流器使用

          本文链接:https://www.haomeiwen.com/subject/kgqdxqtx.html