Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >超详细的Guava RateLimiter限流原理解析

超详细的Guava RateLimiter限流原理解析

原创
作者头像
程序员历小冰
发布于 2019-03-31 01:51:27
发布于 2019-03-31 01:51:27
18.4K0
举报
文章被收录于专栏:程序员历小冰程序员历小冰

 限流是保护高并发系统的三把利器之一,另外两个是缓存和降级。限流在很多场景中用来限制并发和请求量,比如说秒杀抢购,保护自身系统和下游系统不被巨型流量冲垮等。

 限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务或进行流量整形。

 常用的限流方式和场景有:限制总并发数(比如数据库连接池、线程池)、限制瞬时并发数(如nginx的limit_conn模块,用来限制瞬时并发连接数,Java的Semaphore也可以实现)、限制时间窗口内的平均速率(如Guava的RateLimiter、nginx的limit_req模块,限制每秒的平均速率);其他还有如限制远程接口调用速率、限制MQ的消费速率。另外还可以根据网络连接数、网络流量、CPU或内存负载等来限流。

 比如说,我们需要限制方法被调用的并发数不能超过100(同一时间并发数),则我们可以用信号量Semaphore实现。可如果我们要限制方法在一段时间内平均被调用次数不超过100,则需要使用RateLimiter

限流的基础算法

 我们先来讲解一下两个限流相关的基本算法:漏桶算法和令牌桶算法。

漏桶算法
漏桶算法

 从上图中,我们可以看到,就像一个漏斗一样,进来的水量就好像访问流量一样,而出去的水量就像是我们的系统处理请求一样。当访问流量过大时,这个漏斗中就会积水,如果水太多了就会溢出。

 漏桶算法的实现往往依赖于队列,请求到达如果队列未满则直接放入队列,然后有一个处理器按照固定频率从队列头取出请求进行处理。如果请求量大,则会导致队列满,那么新来的请求就会被抛弃。

漏桶算法示意图
漏桶算法示意图

 令牌桶算法则是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。桶中存放的令牌数有最大上限,超出之后就被丢弃或者拒绝。当流量或者网络请求到达时,每个请求都要获取一个令牌,如果能够获取到,则直接处理,并且令牌桶删除一个令牌。如果获取不同,该请求就要被限流,要么直接丢弃,要么在缓冲区等待。

令牌桶算法示意图
令牌桶算法示意图

令牌桶和漏桶对比:

  • 令牌桶是按照固定速率往桶中添加令牌,请求是否被处理需要看桶中令牌是否足够,当令牌数减为零时则拒绝新的请求;漏桶则是按照常量固定速率流出请求,流入请求速率任意,当流入的请求数累积到漏桶容量时,则新流入的请求被拒绝;
  • 令牌桶限制的是平均流入速率,允许突发请求,只要有令牌就可以处理,支持一次拿3个令牌,4个令牌;漏桶限制的是常量流出速率,即流出速率是一个固定常量值,比如都是1的速率流出,而不能一次是1,下次又是2,从而平滑突发流入速率;
  • 令牌桶允许一定程度的突发,而漏桶主要目的是平滑流出速率;

Guava RateLimiter

Guava是Java领域优秀的开源项目,它包含了Google在Java项目中使用一些核心库,包含集合(Collections),缓存(Caching),并发编程库(Concurrency),常用注解(Common annotations),String操作,I/O操作方面的众多非常实用的函数。

 Guava的RateLimiter提供了令牌桶算法实现:平滑突发限流(SmoothBursty)和平滑预热限流(SmoothWarmingUp)实现。

类图
类图

RateLimiter的类图如上所示,其中RateLimiter是入口类,它提供了两套工厂方法来创建出两个子类。这很符合《Effective Java》中的用静态工厂方法代替构造函数的建议,毕竟该书的作者也正是Guava库的主要维护者,二者配合"食用"更佳。

代码语言:txt
AI代码解释
复制
// RateLimiter提供了两个工厂方法,最终会调用下面两个函数,生成RateLimiter的两个子类。
static RateLimiter create(SleepingStopwatch stopwatch, double permitsPerSecond) {
    RateLimiter rateLimiter = new SmoothBursty(stopwatch, 1.0 /* maxBurstSeconds */);
    rateLimiter.setRate(permitsPerSecond);
    return rateLimiter;
}
static RateLimiter create(
    SleepingStopwatch stopwatch, double permitsPerSecond, long warmupPeriod, TimeUnit unit,
    double coldFactor) {
    RateLimiter rateLimiter = new SmoothWarmingUp(stopwatch, warmupPeriod, unit, coldFactor);
    rateLimiter.setRate(permitsPerSecond);
    return rateLimiter;
}
平滑突发限流

 使用RateLimiter的静态方法创建一个限流器,设置每秒放置的令牌数为5个。返回的RateLimiter对象可以保证1秒内不会给超过5个令牌,并且以固定速率进行放置,达到平滑输出的效果。

代码语言:txt
AI代码解释
复制
public void testSmoothBursty() {
    RateLimiter r = RateLimiter.create(5);
    while (true) {
      System.out.println("get 1 tokens: " + r.acquire() + "s");
    }
    /**
     * output: 基本上都是0.2s执行一次,符合一秒发放5个令牌的设定。
     * get 1 tokens: 0.0s 
     * get 1 tokens: 0.182014s
     * get 1 tokens: 0.188464s
     * get 1 tokens: 0.198072s
     * get 1 tokens: 0.196048s
     * get 1 tokens: 0.197538s
     * get 1 tokens: 0.196049s
     */
}

RateLimiter使用令牌桶算法,会进行令牌的累积,如果获取令牌的频率比较低,则不会导致等待,直接获取令牌。

代码语言:txt
AI代码解释
复制
public void testSmoothBursty2() {
    RateLimiter r = RateLimiter.create(2);
    while (true)
    {
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      try {
        Thread.sleep(2000);
      } catch (Exception e) {}
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("end");
      /**
       * output:
       * get 1 tokens: 0.0s
       * get 1 tokens: 0.0s
       * get 1 tokens: 0.0s
       * get 1 tokens: 0.0s
       * end
       * get 1 tokens: 0.499796s
       * get 1 tokens: 0.0s
       * get 1 tokens: 0.0s
       * get 1 tokens: 0.0s
       */
    }
}

RateLimiter由于会累积令牌,所以可以应对突发流量。在下面代码中,有一个请求会直接请求5个令牌,但是由于此时令牌桶中有累积的令牌,足以快速响应。

RateLimiter在没有足够令牌发放时,采用滞后处理的方式,也就是前一个请求获取令牌所需等待的时间由下一次请求来承受,也就是代替前一个请求进行等待。

代码语言:txt
AI代码解释
复制
public void testSmoothBursty3() {
    RateLimiter r = RateLimiter.create(5);
    while (true)
    {
      System.out.println("get 5 tokens: " + r.acquire(5) + "s");
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("end");
      /**
       * output:
       * get 5 tokens: 0.0s
       * get 1 tokens: 0.996766s 滞后效应,需要替前一个请求进行等待
       * get 1 tokens: 0.194007s
       * get 1 tokens: 0.196267s
       * end
       * get 5 tokens: 0.195756s
       * get 1 tokens: 0.995625s 滞后效应,需要替前一个请求进行等待
       * get 1 tokens: 0.194603s
       * get 1 tokens: 0.196866s
       */
    }
}
平滑预热限流

RateLimiterSmoothWarmingUp是带有预热期的平滑限流,它启动后会有一段预热期,逐步将分发频率提升到配置的速率。

 比如下面代码中的例子,创建一个平均分发令牌速率为2,预热期为3分钟。由于设置了预热时间是3秒,令牌桶一开始并不会0.5秒发一个令牌,而是形成一个平滑线性下降的坡度,频率越来越高,在3秒钟之内达到原本设置的频率,以后就以固定的频率输出。这种功能适合系统刚启动需要一点时间来“热身”的场景。

代码语言:txt
AI代码解释
复制
public void testSmoothwarmingUp() {
    RateLimiter r = RateLimiter.create(2, 3, TimeUnit.SECONDS);
    while (true)
    {
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("get 1 tokens: " + r.acquire(1) + "s");
      System.out.println("end");
      /**
       * output:
       * get 1 tokens: 0.0s
       * get 1 tokens: 1.329289s
       * get 1 tokens: 0.994375s
       * get 1 tokens: 0.662888s  上边三次获取的时间相加正好为3秒
       * end
       * get 1 tokens: 0.49764s  正常速率0.5秒一个令牌
       * get 1 tokens: 0.497828s
       * get 1 tokens: 0.49449s
       * get 1 tokens: 0.497522s
       */
    }
}

源码分析

 看完了RateLimiter的基本使用示例后,我们来学习一下它的实现原理。先了解一下几个比较重要的成员变量的含义。

代码语言:txt
AI代码解释
复制
//SmoothRateLimiter.java
//当前存储令牌数
double storedPermits;
//最大存储令牌数
double maxPermits;
//添加令牌时间间隔
double stableIntervalMicros;
/**
 * 下一次请求可以获取令牌的起始时间
 * 由于RateLimiter允许预消费,上次请求预消费令牌后
 * 下次请求需要等待相应的时间到nextFreeTicketMicros时刻才可以获取令牌
 */
private long nextFreeTicketMicros = 0L;
平滑突发限流

RateLimiter的原理就是每次调用acquire时用当前时间和nextFreeTicketMicros进行比较,根据二者的间隔和添加单位令牌的时间间隔stableIntervalMicros来刷新存储令牌数storedPermits。然后acquire会进行休眠,直到nextFreeTicketMicros

acquire函数如下所示,它会调用reserve函数计算获取目标令牌数所需等待的时间,然后使用SleepStopwatch进行休眠,最后返回等待时间。

代码语言:txt
AI代码解释
复制
public double acquire(int permits) {
    // 计算获取令牌所需等待的时间
    long microsToWait = reserve(permits);
    // 进行线程sleep
    stopwatch.sleepMicrosUninterruptibly(microsToWait);
    return 1.0 * microsToWait / SECONDS.toMicros(1L);
}
final long reserve(int permits) {
    checkPermits(permits);
    // 由于涉及并发操作,所以使用synchronized进行并发操作
    synchronized (mutex()) {
      return reserveAndGetWaitLength(permits, stopwatch.readMicros());
    }
}
final long reserveAndGetWaitLength(int permits, long nowMicros) {
    // 计算从当前时间开始,能够获取到目标数量令牌时的时间
    long momentAvailable = reserveEarliestAvailable(permits, nowMicros);
    // 两个时间相减,获得需要等待的时间
    return max(momentAvailable - nowMicros, 0);
}

reserveEarliestAvailable是刷新令牌数和下次获取令牌时间nextFreeTicketMicros的关键函数。它有三个步骤,一是调用resync函数增加令牌数,二是计算预支付令牌所需额外等待的时间,三是更新下次获取令牌时间nextFreeTicketMicros和存储令牌数storedPermits

 这里涉及RateLimiter的一个特性,也就是可以预先支付令牌,并且所需等待的时间在下次获取令牌时再实际执行。详细的代码逻辑的解释请看注释。

代码语言:txt
AI代码解释
复制
final long reserveEarliestAvailable(int requiredPermits, long nowMicros) {
    // 刷新令牌数,相当于每次acquire时在根据时间进行令牌的刷新
    resync(nowMicros);
    long returnValue = nextFreeTicketMicros;
    // 获取当前已有的令牌数和需要获取的目标令牌数进行比较,计算出可以目前即可得到的令牌数。
    double storedPermitsToSpend = min(requiredPermits, this.storedPermits);
    // freshPermits是需要预先支付的令牌,也就是目标令牌数减去目前即可得到的令牌数
    double freshPermits = requiredPermits - storedPermitsToSpend;
    // 因为会突然涌入大量请求,而现有令牌数又不够用,因此会预先支付一定的令牌数
    // waitMicros即是产生预先支付令牌的数量时间,则将下次要添加令牌的时间应该计算时间加上watiMicros
    long waitMicros = storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
        + (long) (freshPermits * stableIntervalMicros);
    // storedPermitsToWaitTime在SmoothWarmingUp和SmoothBuresty的实现不同,用于实现预热缓冲期
    // SmoothBuresty的storedPermitsToWaitTime直接返回0,所以watiMicros就是预先支付的令牌所需等待的时间
    try {
      // 更新nextFreeTicketMicros,本次预先支付的令牌所需等待的时间让下一次请求来实际等待。
      this.nextFreeTicketMicros = LongMath.checkedAdd(nextFreeTicketMicros, waitMicros);
    } catch (ArithmeticException e) {
      this.nextFreeTicketMicros = Long.MAX_VALUE;
    }
    // 更新令牌数,最低数量为0
    this.storedPermits -= storedPermitsToSpend;
    // 返回旧的nextFreeTicketMicros数值,无需为预支付的令牌多加等待时间。
    return returnValue;
}
// SmoothBurest
long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
    return 0L;
}

resync函数用于增加存储令牌,核心逻辑就是(nowMicros - nextFreeTicketMicros) / stableIntervalMicros。当前时间大于nextFreeTicketMicros时进行刷新,否则直接返回。

代码语言:txt
AI代码解释
复制
void resync(long nowMicros) {
    // 当前时间晚于nextFreeTicketMicros,所以刷新令牌和nextFreeTicketMicros
    if (nowMicros > nextFreeTicketMicros) {
      // coolDownIntervalMicros函数获取每机秒生成一个令牌,SmoothWarmingUp和SmoothBuresty的实现不同
      // SmoothBuresty的coolDownIntervalMicros直接返回stableIntervalMicros
      // 当前时间减去要更新令牌的时间获取时间间隔,再除以添加令牌时间间隔获取这段时间内要添加的令牌数
      storedPermits = min(maxPermits,
          storedPermits
            + (nowMicros - nextFreeTicketMicros) / coolDownIntervalMicros());
      nextFreeTicketMicros = nowMicros;
    }
    // 如果当前时间早于nextFreeTicketMicros,则获取令牌的线程要一直等待到nextFreeTicketMicros,该线程获取令牌所需
    // 额外等待的时间由下一次获取的线程来代替等待。
}
double coolDownIntervalMicros() {
    return stableIntervalMicros;
}

 下面我们举个例子,让大家更好的理解resyncreserveEarliestAvailable函数的逻辑。

 比如RateLimiterstableIntervalMicros为500,也就是1秒发两个令牌,storedPermits为0,nextFreeTicketMicros为1553918495748。线程一acquire(2),当前时间为1553918496248,首先resync函数计算,(1553918496248 - 1553918495748)/500 = 1,所以当前可获取令牌数为1,但是由于可以预支付,所以nextFreeTicketMicros= nextFreeTicketMicro + 1 * 500 = 1553918496748。线程一无需等待。

 紧接着,线程二也来acquire(2),首先resync函数发现当前时间早于nextFreeTicketMicros,所以无法增加令牌数,所以需要预支付2个令牌,nextFreeTicketMicros= nextFreeTicketMicro + 2 * 500 = 1553918497748。线程二需要等待1553918496748时刻,也就是线程一获取时计算的nextFreeTicketMicros时刻。同样的,线程三获取令牌时也需要等待到线程二计算的nextFreeTicketMicros时刻。

平滑预热限流

 上述就是平滑突发限流RateLimiter的实现,下面我们来看一下加上预热缓冲期的实现原理。

SmoothWarmingUp实现预热缓冲的关键在于其分发令牌的速率会随时间和令牌数而改变,速率会先慢后快。表现形式如下图所示,令牌刷新的时间间隔由长逐渐变短。等存储令牌数从maxPermits到达thresholdPermits时,发放令牌的时间价格也由coldInterval降低到了正常的stableInterval。

image.png
image.png

SmoothWarmingUp的相关代码如下所示,相关的逻辑都写在注释中。

代码语言:txt
AI代码解释
复制
// SmoothWarmingUp,等待时间就是计算上图中梯形或者正方形的面积。
long storedPermitsToWaitTime(double storedPermits, double permitsToTake) {
    /**
    * 当前permits超出阈值的部分
    */
    double availablePermitsAboveThreshold = storedPermits - thresholdPermits;
    long micros = 0;
    /**
    * 如果当前存储的令牌数超出thresholdPermits
    */
    if (availablePermitsAboveThreshold > 0.0) {
    /**
     * 在阈值右侧并且需要被消耗的令牌数量
     */
    double permitsAboveThresholdToTake = min(availablePermitsAboveThreshold, permitsToTake);

    /**
        * 梯形的面积
        *
        * 高 * (顶 * 底) / 2
        *
        * 高是 permitsAboveThresholdToTake 也就是右侧需要消费的令牌数
        * 底 较长 permitsToTime(availablePermitsAboveThreshold)
        * 顶 较短 permitsToTime(availablePermitsAboveThreshold - permitsAboveThresholdToTake)
        */
    micros = (long) (permitsAboveThresholdToTake
        * (permitsToTime(availablePermitsAboveThreshold)
        + permitsToTime(availablePermitsAboveThreshold - permitsAboveThresholdToTake)) / 2.0);
    /**
        * 减去已经获取的在阈值右侧的令牌数
        */
    permitsToTake -= permitsAboveThresholdToTake;
    }
    /**
    * 平稳时期的面积,正好是长乘宽
    */
    micros += (stableIntervalMicros * permitsToTake);
    return micros;
}

double coolDownIntervalMicros() {
    /**
    * 每秒增加的令牌数为 warmup时间/maxPermits. 这样的话,在warmuptime时间内,就就增张的令牌数量
    * 为 maxPermits
    */
    return warmupPeriodMicros / maxPermits;
}

后记

RateLimiter只能用于单机的限流,如果想要集群限流,则需要引入redis或者阿里开源的sentinel中间件,请大家继续关注。

remcarpediem

参考

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Guava RateLimiter详解以及源码分析
首先你需要明白限流的概念,在高并发、高流量的场景中,我们的系统有时候会通过限流的手段来防止自己的系统被外部的流量打挂,是一种自我保护措施。
用户7634691
2021/08/12
1.1K0
限流算法(Guava RateLimiter)
这种算法很好实现, 但是会出现限流不准确问题。比如每秒通过 5 个请求,时间窗口的大小为 1 秒,当前时间窗口周期内的后半秒正常通过了 5 个请求,下一个时间窗口周期内的前半秒正常通过了 5 个请求,在这两个窗口内都没有超过限制。 但是在这两个窗口的中间那一秒实际上通过了 10 个请求,显然不满足每秒 5 个请求的限制。
leobhao
2022/06/28
8490
限流算法(Guava RateLimiter)
使用Guava RateLimiter限流以及源码解析
首先通过RateLimiter.create(1);创建一个限流器,参数代表每秒生成的令牌数,通过limiter.acquire(i);来以阻塞的方式获取令牌,当然也可以通过tryAcquire(int permits, long timeout, TimeUnit unit)来设置等待超时时间的方式获取令牌,如果超timeout为0,则代表非阻塞,获取不到立即返回。
用户6182664
2020/05/08
1.3K0
使用Guava RateLimiter限流以及源码解析
限速神器RateLimiter源码解析
Tech 导读 在软件系统中,面对高并发的场景,经常需要通过限流来降低系统压力、保护系统不被压垮;另外在交易处理的场景中,也经常因下游要求或其他原因需控制处理速率。RateLimiter是谷歌开源的一款轻巧限流限速组件,简单实用,设计精妙,本文结合示例对其源码进行了相关分析解读,包括代码层级、处理流程、数据流转、计算逻辑等, 希望能够帮助大家了解和使用。
京东技术
2023/08/22
5100
限速神器RateLimiter源码解析
面试官:来谈谈限流-RateLimiter源码分析
RateLimiter有两个实现类:SmoothBursty和SmoothWarmingUp,其都是令牌桶算法的变种实现,区别在于SmoothBursty加令牌的速度是恒定的,而SmoothWarmingUp会有个预热期,在预热期内加令牌的速度是慢慢增加的,直到达到固定速度为止。其适用场景是,对于有的系统而言刚启动时能承受的QPS较小,需要预热一段时间后才能达到最佳状态。
李红
2019/08/13
7940
源码分析 RateLimiter SmoothBursty 实现原理(文末附流程图)
上篇详细介绍了Sentinel FlowSlot 限流实现原理(文末附流程图与总结)的限流实现机制,但主要介绍的策略限流的快速失败机制,在Sentinel 中除了快速失败,还提供了匀速排队,预热等限流策略,但我发现 Sentinel 的匀速排队、预热机制是基于 guava 的 RateLimiter,为了更加彻底的理解 Sentienl 限流相关的内容,从本文开始先来学习一下 RateLimiter 的相关实现原理。
丁威
2020/03/31
1.4K0
源码分析 RateLimiter SmoothBursty 实现原理(文末附流程图)
限流原理解读之guava中的RateLimiter
RateLimiter.create做了两件事情创建Bursty对象和设置了速率,至次初始化过程结束
爬蜥
2019/07/08
1.7K0
Guava RateLimiter限流源码解析和实例应用
Guava有两种限流模式,一种为稳定模式(SmoothBursty:令牌生成速度恒定),一种为渐进模式(SmoothWarmingUp:令牌生成速度缓慢提升直到维持在一个稳定值) 两种模式实现思路类似,主要区别在等待时间的计算上,本篇重点介绍SmoothBursty
算法之名
2019/08/20
8360
Guava RateLimiter限流源码解析和实例应用
令牌桶算法原理及应用
最近在参与一个业务迁移的项目。走读代码时,接触到一些限流相关的代码。向老司机请教后了解到,有些业务承载了很高量级的扣款请求,尤其对于一些热点商户,其单点的请求量很大,但某些瓶颈系统的处理能力有限,因此需要做好限流,以保障业务流程中各系统的稳定性。
张乘辉
2022/01/24
4K0
令牌桶算法原理及应用
源码分析RateLimiter SmoothWarmingUp 实现原理(文末附流程图)
上一篇详细介绍了 SmoothBursty 的实现原理,本文将介绍带有预热机制的限速器实现原理。
丁威
2020/03/31
1.5K0
源码分析RateLimiter SmoothWarmingUp 实现原理(文末附流程图)
聊聊Guava的RateLimiter
guava-26.0-jre-sources.jar!/com/google/common/util/concurrent/RateLimiter.java
code4it
2018/09/17
2.8K0
基本限流算法与GuavaRateLimiter实现
总结: 固定窗口算法适用于对请求速率有明确要求且流量相对稳定的场景,但对于突发流量和请求分布不均匀的情况,可能需要考虑其他更灵活的限流算法。
leobhao
2024/08/07
1440
基本限流算法与GuavaRateLimiter实现
RateLimiter源码分析
如下图所示,我创建一个1秒产生0.1的RateLimiter(即10秒产生1个),左边是时间轴,现在有3个线程申请数据,nextFreeTicketMicros初始化为0(其实他的计算单位是微秒)
CBeann
2023/12/25
2010
RateLimiter源码分析
令牌桶的实现_C语言实现栈
接上篇。Guava的令牌桶的实现中,包括一条设计哲学,需要大家注意:它允许瞬间的流量波峰超过QPS,但瞬间过后的请求将会等待较长的时间来缓解上次的波峰,以使得平均的QPS等于预定值。
全栈程序员站长
2022/09/27
8130
Guava RateLimiter预热模型
我们都知道在做运动之前先得来几组拉伸之类的动作,给身体做个热身,让我们的身体平滑过渡到后面的剧烈运动中。流量预热也是一样的道理,对限流组件来说,流量预热就类似于一种热身运动,它可以动态调整令牌发放速度,让流量变化更加平滑。
程序员波特
2024/01/19
2150
Guava RateLimiter预热模型
源码解析:Guava客户端限流
客户端限流:当应用为单点应用时,只要应用进行了限流,那么应用所依赖的各种服务也都得到了保护。
后台技术汇
2024/09/15
1520
源码解析:Guava客户端限流
常见限流算法及其实现
在分布式系统中,随着业务量的增长,如何保护核心资源、防止系统过载、保证系统的稳定性成为了一个重要的问题。限流算法作为一种有效的流量控制手段,被广泛应用于各类系统中。本文将详细介绍四种常见的限流算法、两种常用的限流器工具,从原理、源码的角度进行分析。
掂过碌蔗啊
2024/03/05
4700
RateLimiter没有用到集合,核心是一个时间值
令牌桶的图,网上到处可见,按图实现也非常简单,无非是定时添加令牌桶,并提供一个获取令牌的函数,博主实现了一遍代码如下:
温安适
2021/02/27
3020
RateLimiter没有用到集合,核心是一个时间值
​什么是限流,如何限流
某天小明突然发现自己的接口请求突然之间涨到了原来的10倍,接口几乎不能使用,产生了一系列连锁反应,导致了整个系统崩溃。这就好比,老电闸中都安装了保险丝,一旦使用大功率设备,保险丝就会熔断,保证各个电器不被强电流烧坏,系统也同样安装保险丝,防止非预期请求过大,引起系统瘫痪。
王小明_HIT
2021/05/20
3.3K0
高并发之限流,到底限的什么鬼 (精品长文)
你可能知道高并发系统需要限流这个东西,但具体是限制的什么,该如何去做,还是模凌两可。我们接下来系统性的给它归个小类,希望对你有所帮助。
xjjdog
2019/07/10
1.1K0
高并发之限流,到底限的什么鬼 (精品长文)
相关推荐
Guava RateLimiter详解以及源码分析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档