Search code examples
javaraterate-limiting

Rate limiting outgoing requests in Java but with a dynamic rate


I am building an application which includes a scraper of a public API. I want to limit the rate of my requests but not with a fixed rate, but a dynamic randomised rate which changes in-between requests and falls in a certain range, i.e. I can set the minimum and maximum delay between requests.

I also don't want to block the current thread.

I've researched Guava Ratelimiter, RatelimitJ and Token bucket algorithm but looking at the docs, I don't see how any of those things can achieve what I want.

Example of the desired effect on my requests given a rate limit range of 250-350ms:

  • Make request #1
  • wait 321ms
  • Make request #2
  • wait 259ms
  • Make request #3
  • wait 337ms
  • ...

Solution

  • You don't need to look outside the JDK. You can use java.util.concurrent.ScheduledExecutorService to make the call after a defined delay and in a separate thread. To use this you will need to implement java.util.concurrent.Callable or java.lang.Runnable for the code that does the API call.

        ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
        Callable apiCaller = ...;
    

    To make the call so that it runs after a defined delay you submit it as follows:

        service.schedule(apiCaller, delay, TimeUnit.MILLISECONDS);
    

    To get a random delay you just need to use java.util.Random.

            Random random = new Random();
    

    Random can provide you with a bounded integer. So if you pass it the acceptable range and then add then add the minimum you will get a random number between the minimum and maximum you want.

       int minimumDelay = 250;
       int maximumDelay = 350;       
       int delay = random.nextInt(maximumDelay - minimumDelay) + minimumDelay;