Guavas RateLimiter per minute instead of seconds?

I am trying to limit the number of accounts that a user can create using my REST API.

I would like to use Guava RateLimiterto allow IP to create, say, 5 accounts in 10 minutes, but the method RateLimiter.createonly accepts the doublenumber of permissions per second.

Is there a way to configure RateLimiter to issue permissions with more granularity for more than one second?

+7
source share
5 answers

From RateLimiter.createjavadoc:

PerSecond, (1.0 / permitsPerSecond) .

, permitsPerSecond 1.0, , .

, 120 . 1.0/120 permitsPerSecond.

, , . RateLimiter, -, , , SmoothRateLimiter, -, . , javadoc, SmoothRateLimiter .

+11

Guava SmoothRateLimiter.SmoothBursty, , , . Github public: https://github.com/google/guava/issues/1974

, RateLimiter, SmoothBursty. - :

Class<?> sleepingStopwatchClass = Class.forName("com.google.common.util.concurrent.RateLimiter$SleepingStopwatch");
Method createStopwatchMethod = sleepingStopwatchClass.getDeclaredMethod("createFromSystemTimer");
createStopwatchMethod.setAccessible(true);
Object stopwatch = createStopwatchMethod.invoke(null);

Class<?> burstyRateLimiterClass = Class.forName("com.google.common.util.concurrent.SmoothRateLimiter$SmoothBursty");
Constructor<?> burstyRateLimiterConstructor = burstyRateLimiterClass.getDeclaredConstructors()[0];
burstyRateLimiterConstructor.setAccessible(true);

RateLimiter result = (RateLimiter) burstyRateLimiterConstructor.newInstance(stopwatch, maxBurstSeconds);
result.setRate(permitsPerSecond);
return result;

, Guava , , .

+4

120 .

+3

, , , Louis Wasserman comment , :

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

}

, , . , , , . , , , , , .

tryConsume() RateLimiter tryAcquire , numDosesAvailable .

+1

Just in case, if you skip it, RateLimiter will determine what happened to the unused permission. The default behavior is to keep an unused link for up to one minute RateLimiter .

0
source

Source: https://habr.com/ru/post/1569468/


All Articles