动态观察 RateLimiter

guava 16版本中的WarmingUp 的许可,即storedPermits是字段,是非常关键的属性,它会随时间推移不断的变化,我们怎么样即使的动态观察它呢? 
因为它是私有字段,而且是惰性的,因为因为RateLimiter 允许提前消费,这意味着它确实比较难观察。
 
我想到了下面的方法:
 
    public void testSmoothwarmingUp() throws Exception {
        RateLimiter r = RateLimiter.create(2, 3, TimeUnit.SECONDS);

        Class<RateLimiter> rateLimiterClass = RateLimiter.class;
        Field storedPermits = rateLimiterClass.getDeclaredField("storedPermits");// 必须要getDeclaredField, 不能getField
        storedPermits.setAccessible(true);
        ReflectionUtils.makeAccessible(storedPermits);
        Object o = storedPermits.get(r);
        System.out.println(o + " get 1 tokens: ++++++++ "  + 000000);
        try {
            Thread.sleep(3000);
        } catch (Exception e) {
            e.printStackTrace();
        }

        while (true)
        {
            o = storedPermits.get(r);
            System.out.println(o + " get 1 tokens: " + r.acquire(3) + "s");// 前3个permets耗时warmupPeriod,
            o = storedPermits.get(r);
            System.out.println(o + " get 1 tokens: " + r.acquire(1) + "s");
            o = storedPermits.get(r);
            System.out.println(o + " get 1 tokens: " + r.acquire(1) + "s");// 第四个permets之后 速率已经达到最高,完全稳定。
            o = storedPermits.get(r);
            System.out.println(o + " get 1 tokens: " + r.acquire(1) + "s");
            o = storedPermits.get(r);
            System.out.println("o = " + o);
            /**
             * 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
             */
            System.out.println(o + " get 1 tokens: " + r.acquire(3) + "s");

            try {
                int millis = 4000;

                // 不管之前是什么情况,不管之前acquire多少, 这里只要sleep超过warmupPeriod时间, 就会完全冷却 // xxx 错错错
                // 不管之前是什么情况,只要上一个acquire小于maxPermits - thresholdPermits, 这里只要sleep超过warmupPeriod时间, 就会完全冷却
                Thread.sleep(millis); // sleep warmupPeriod + extra时间, 可以保证完全冷却;extra时间是指
//                Thread.sleep(millis); // 债务还清之后(即过了extra时间之后),再sleep warmupPeriod/2 时间,将处于临界点:storedPermits = thresholdPermits
                System.out.println("sleep  " + millis);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

//            boolean b = r.tryAcquire(6);

            r.setRate(r.getRate());// 通过此方法触发resync方法,进而可以设置storedPermits字段的值为最新值

            o = storedPermits.get(r);// 当限流器经过warmupPeriod时间之后,它就会完全冷却,不过此时 无法观察到storedPermits字段,因为它是惰性的
            System.out.println(o + " get 1 tokens: " + r.acquire(1) + "s");
            o = storedPermits.get(r);
            System.out.println(o + " get 1 tokens: " + r.acquire(2) + "s");
            o = storedPermits.get(r);
            System.out.println(o + " get 1 tokens: " + r.acquire(3) + "s");
            o = storedPermits.get(r);
            System.out.println(o + " get 1 tokens: " + r.acquire(1) + "s");
            o = storedPermits.get(r);
            System.out.println(o + " get 1 tokens: " + r.acquire(1) + "s");
            o = storedPermits.get(r);
            System.out.println(o + " get 3 tokens: " + r.acquire(3) + "s");
            System.out.println("end"); 
        }
 
 
这样之后,测试、观察就方便多了!!
 
 


版权声明
本文原创发表于 博客园,作者为 阿K .     本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
欢迎关注本人微信公众号:觉醒的码农,或者扫码进群:

原文地址:https://www.cnblogs.com/FlyAway2013/p/14651386.html