zoukankan      html  css  js  c++  java
  • RateLimiter限流器

    • RateLimiter是基于令牌桶算法实现的一个多线程限流器,它可以将请求均匀的进行处理,当然他并不是一个分布式限流器,只是对单机进行限流。它可以应用在定时拉取接口数。 通过aop、filter、Interceptor 等都可以达到限流效果。
    原理特别简单、轻量。引入guava包即可。
    package com.ratelimiter;
    
    import com.google.common.util.concurrent.RateLimiter;
    
    import static java.util.concurrent.TimeUnit.MILLISECONDS;
    import static java.util.concurrent.TimeUnit.SECONDS;
    
    /**
     * RateLimiter是基于令牌桶算法实现的一个多线程限流器,它可以将请求均匀的进行处理,当然他并不是一个分布式限流器,只是对单机进行限流。它可以应用在定时拉取接口数据,
     *
     * @version 1.0
     * @date 2020-06-11 10:08
     **/
    public class RateMain {
    
        public static void main(String[] args) throws InterruptedException {
            long l = MILLISECONDS.toMicros(1L);
            long l1 = MILLISECONDS.toMillis(1L);
            long l2 = SECONDS.toMicros(1L);
            System.out.println("RateMain.main = " + l + "====" + l1 + "====" + l2);
            System.out.println("RateMain.main jdk8 新特性无穷大 = " + ((1.0 / 0.0) > 9.99));
            RateLimiter rateLimiter = RateLimiter.create(1000);
            MILLISECONDS.sleep(1000L); // sleep 1s, 那么会导致初始化10个令牌
            int i = 0;
            do {
                long start = System.currentTimeMillis();
                boolean b = rateLimiter.tryAcquire();
    //            double b = rateLimiter.acquire();  // 取的令牌,返回获取令牌的耗时。
                System.out.print(System.currentTimeMillis() - start);
                System.out.println("第" + (++i) + "条, 获取令牌:" + b);
                if (i > 50) {
                    break;
                }
            } while (true);
        }
    }

    原理

    首先先讲一下令牌桶的原理,每隔一段时间生产一个令牌放入桶里,请求在执行时需要拿到令牌才可以执行,如果拿不到令牌将等待令牌产生,一个生产者,多个消费者。

    但是这样的令牌桶有一个问题,如果CPU负载过高,生产令牌的线程没有获取到时间片生产令牌,那么限制的流量将会比设定值更低。

    可能是出于这个原因,guava并没有这样做,而是一个惰性生产令牌:

    每次请求令牌时,通过当前时间和下次产生令牌时间的差值计算出现在有多少个令牌。
    storedPermits: 已有令牌数量
    nextFreeTicketMicros: 下次产生令牌的时间点
    stableIntervalMicros: 产生一个令牌需要的时间,例如10qps,  = 1000/10 = 100ms会产生一个令牌

    例如:获取令牌时,当前时间比下次产生令牌时间大,
    会计算出令牌存储[(now-nextFreeTicketMicros)/stableIntervalMicros],如果令牌不够,则让线程sleep;
    每次新生产令牌,下次产生令牌的时间点更新成当前时间时间(有等待,需要加上等待时间)。

    断点进去就可以了。

  • 相关阅读:
    常见优化函数
    排序算法
    小米编程题
    leetcode 刷题
    beam_search 和 viterbi算法的区别
    快速排序
    vitrebi算法进行分词的案例
    python 进行视频剪辑
    keras实现MobileNet
    HMM、CTC、RNN-T训练时所有alignment的寻找方法
  • 原文地址:https://www.cnblogs.com/bestzhang/p/13094766.html
Copyright © 2011-2022 走看看