Spreading the load more evenly from a background thread I have a background thread which runs every 5 minutes. I am using ScheduledExecutorService for this. Every five minutes, I am making a call to one of my service and parsing the response coming back from that service.

public class ThreadScheduler {

private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public void startScheduleTask() {

        scheduler.scheduleAtFixedRate(new Runnable() {
            public void run() {
                try {
                    callService();
                } catch (Exception ex) {
                    // log error
                }
            }
        }, 0, 5L, TimeUnit.MINUTES);
    }

    public void callService() throws Exception {
        // execute the service and parse the response
    }   
}


Now the above code is running in 1000 machines and they all are started at the same time, so that means it will make all the 1000 calls every 5 minutes simultaneously to my service.  I'm trying to spread the load more evenly over a 5 minute window. Is this possible to do by any chance with the above code?

I am just trying to spread the load more evenly on my service over the 5 minute window so that it doesn't hit my service at the same time which will put more load once all the systems are started up  simultaneously.

I came up with the below code trying to spread the load more evenly over the five minute window:

public class ThreadScheduler {

private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public void startScheduleTask() {

        scheduler.scheduleAtFixedRate(new Runnable() {
            public void run() {
                try {
                    callService();
                } catch (Exception ex) {
                    // log error
                }
            }
        }, (int)(Math.random()*5*60), 5*60L, TimeUnit.SECONDS);
    }

    public void callService() throws Exception {
        // execute the service and parse the response
    }   
}


I am opting for code review to see whether this way load will get evenly spread out over the 5 minute window or not.
If you use a random delay and fixed period, all machines will make roughly the same number of calls during their lifetime. With this approach you can be sure that every machine makes a call within the period.

If you use a fixed delay and random period, then some machines may end up making more calls than average, and others less than average.

If you want more balanced calls, the first approach makes more sense.

To measure the actual load, add some logging on the server. To give you an example, given this simplified sample from an apache log:


66.249.67.190 - - [30/Aug/2014:04:28:23 -0700] "GET
66.249.67.203 - - [30/Aug/2014:04:28:34 -0700] "GET
66.249.65.126 - - [30/Aug/2014:05:32:54 -0700] "GET
66.249.65.126 - - [30/Aug/2014:05:32:54 -0700] "GET
66.249.65.118 - - [30/Aug/2014:08:11:20 -0700] "GET
66.249.65.118 - - [30/Aug/2014:08:11:20 -0700] "GET
66.249.65.126 - - [30/Aug/2014:08:11:21 -0700] "GET
180.76.5.168 - - [30/Aug/2014:14:30:57 -0700] "GET



I would extract the timestamp part using cut or awk commands, for example:


# extract the timestamp part, until minutes, without seconds
cat access.log | cut -d' ' -f4 | cut -d: -f-2
[30/Aug/2014:04
[30/Aug/2014:04
[30/Aug/2014:05
[30/Aug/2014:05
[30/Aug/2014:08
[30/Aug/2014:08
[30/Aug/2014:08
[30/Aug/2014:14



And pipe this to uniq -c to get a count per-minute:


cat access.log | cut -d' ' -f4 | cut -d: -f-2 | uniq -c
  2 [30/Aug/2014:04
  2 [30/Aug/2014:05
  3 [30/Aug/2014:08
  1 [30/Aug/2014:14



Hopefully you should see a balanced count, and a repeating pattern every 5 minutes.

This is just an example (and not the best way, quick and dirty way) of measuring the load, use whatever method that suits you best.