Guava’s RateLimiter per minutes instead of seconds?

前端 未结 6 2324
情话喂你
情话喂你 2021-02-13 21:28

I\'m trying to rate-limit the the number of accounts a user can create with my REST API.

I would have liked to use Guava\'s RateLimiter to only allow an IP

6条回答
  •  野性不改
    2021-02-13 21:45

    I think I came upon the same problem as in the original question, and based on Louis Wasserman's comment this is what I drew up:

    import com.google.common.util.concurrent.RateLimiter;
    import java.time.Duration;
    
    public class Titrator {
    
        private final int numDosesPerPeriod;
        private final RateLimiter rateLimiter;
        private long numDosesAvailable;
        private transient final Object doseLock;
    
        public Titrator(int numDosesPerPeriod, Duration period) {
            this.numDosesPerPeriod = numDosesPerPeriod;
            double numSeconds = period.getSeconds() + period.getNano() / 1000000000d;
            rateLimiter = RateLimiter.create(1 / numSeconds);
            numDosesAvailable = 0L;
            doseLock = new Object();
        }
    
        /**
         * Consumes a dose from this titrator, blocking until a dose is available.
         */
        public void consume() {
            synchronized (doseLock) {
                if (numDosesAvailable == 0) { // then refill
                    rateLimiter.acquire();
                    numDosesAvailable += numDosesPerPeriod;
                }
                numDosesAvailable--;
            }
        }
    
    }
    

    The dose meted out by the Titrator is analogous to a permit from a RateLimiter. This implementation assumes that when you consume your first dose, the clock starts ticking on the dosage period. You can consume your max doses per period as fast as you want, but when you reach your max, you have to wait until the period elapses before you can get another dose.

    For a tryConsume() analog to RateLimiter's tryAcquire, you would check that numDosesAvailable is positive.

提交回复
热议问题