动态观察 RateLimiter - WarmingUp 的许可变化

 

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"); 
        }
 

 

  这样之后,测试、观察就方便多了!!    
上一篇:JZ86 在二叉树中找到两个节点的最近公共祖先


下一篇:Aop结合Guava实现的接口的限流保护(单机版)