Haim
Haim

Reputation: 63

How to run a task in fixed intervals in a multiple-instances Tomcat env.?

I'm scheduling background task to run in fixed-intervals, but as tomcat is running in multiple instances (i.e. multiple start Apache servers; 3 in my case), then the task runs 3 times in each interval.. I would like it to run once (no matter the number of Tomcat instances running).

I'm running a servlet loaded on startup (in web.xml) which will initiate my task:

<servlet>
    <servlet-name>OnInit</servlet-name>
    <servlet-class>box.OnInit</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet> 

OnInit class initiate single instance of that class:

public class BGTaskRefresh {
    private static BGTaskRefresh refreshTaskFactory = null;
    private final Timer timer = new Timer();

    public BGTaskRefresh() {}
    public static void init()
    {
        if( refreshTaskFactory == null )
        {
            refreshTaskFactory = new BGTaskRefresh();
            refreshTaskFactory.start();
        }
    }

    public void start() 
    {
        timer.schedule(
            new TimerTask() 
            {
                    public void run() 
                    {
                        boxService box = new boxService();
                        box.refreshMethod();
                    } 
                },                      
                5 * 60 * 1000,   // 5-Min Delay for first run
            60 * 60 * 1000); // 60-Mins (Interval between 2 runs)                   
    }
}

Upvotes: 3

Views: 1047

Answers (2)

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340723

You might want to have a look at , especially its clustering capabilities:

two muppets
(source: quartz-scheduler.org)

This might be an overkill in your situation, but Quartz will take care of running the job on only a single instance (using database for synchronization) and will automatically run the job on an idle server.

Another option is and distributed locks and queues it provides.

Upvotes: 3

Tomer Gabel
Tomer Gabel

Reputation: 4112

You will need some sort of synchronization mechanism. Although ideally you'd want a distributed scheduler (e.g. Quartz cluster), considering your usage scenario you're likely to have either some mechanism for shared session state or a shared database underlying your application; you can simply record the operation and grab a database-based lock to ensure only one instance will run the command at a time (and double-check after the lock grab to ensure you're not running the same task twice).

Here's one article I've found with a technique for DB-based locking: http://blog.udby.com/archives/15

Upvotes: 0

Related Questions