The steps for configuring a clustered environment for Quartz are much easier than for setting an equivalent environment for a J2EE cluster:
Configure each node's quartz.properties file.
Configure the JDBC JobStore.
Load the database with Scheduler information (jobs and triggers).
Start each Quartz node.
Configuring the Node's quartz.properties File
Just as when running Quartz in a nonclustered environment, each Quartz application requires a quartz.properties file. As mentioned in Chapter 3, "Hello, Quartz," if you don't specify one, the default quartz.properties file (within the quartz.jar file) gets used. It's best to always specify one because you will eventually need to modify one or more of the settings.
When using the clustered features of Quartz, you need to modify the quartz.properties file for each node. Listing 11.1 shows an example quartz.properties file that is used for a clustered instance. The properties are discussed after the listing.
Listing 11.1. Sample quartz.properties for Clustered Instance
#============================================================== #Configure Main Scheduler Properties #============================================================== org.quartz.scheduler.instanceName = TestScheduler1 org.quartz.scheduler.instanceId = instance_one #============================================================== #Configure ThreadPool #============================================================== org.quartz.threadPool.class = org.quartz.simpl.Simple ThreadPool org.quartz.threadPool.threadCount = 5 org.quartz.threadPool.threadPriority = 5 #============================================================== #Configure JobStore #============================================================== org.quartz.jobStore.misfireThreshold = 60000 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.MSSQLDelegate org.quartz.jobStore.tablePrefix = QRTZ_ org.quartz.jobStore.dataSource = myDS org.quartz.jobStore.isClustered = true org.quartz.jobStore.clusterCheckinInterval = 20000 #============================================================== #Non-Managed Configure Datasource #============================================================== org.quartz.dataSource.myDS.driver = net.sourceforge.jtds.jdbc.Driver org.quartz.dataSource.myDS.URL = jdbc:jtds:sqlserver://localhost:1433/quartz org.quartz.dataSource.myDS.user = admin org.quartz.dataSource.myDS.password = admin org.quartz.dataSource.myDS.maxConnections = 10
Configuring the Main Scheduler Properties
These two properties should be configured in this section:
These properties are used in several places within the JDBC JobStore and database to uniquely identify the instance.
Use the AUTO Feature for Instance ID When Clustering
AUTO was created specifically for clustering. Unfortunately, in some of the earlier versions of the framework, the mechanism in version 1.4.5 didn't clean up old instance IDs in all cases. Version 1.5.1 has a facility for pluggable instance ID generators, one of which creates the ID based on the IP address of the node; this works great as long as you have only one Quartz cluster node on a given machine. AUTO should be used when clustering because many people deploy Quartz within an EAR that is distributed across a cluster of application servers. In this case, there must be a single quartz.properties file that is within the EAR and that is therefore the same for all nodes. If the instance ID was hard coded, the Quartz cluster wouldn't work because all nodes would have the same ID. AUTO thus solves the problem.
Some other serious clustering issues were introduced in Quartz 1.5.1. If you need to cluster Quartz, you probably should avoid that version.
Configuring the JobStore Section
To use clustering with Quartz, you are required to use either JobStoreTX or JobStoreCMT as the Scheduler's JobStore. Chapter 6, "JobStores and Persistence," detailed how to set up and use one of the two provided JDBC JobStores. From Listing 11.1, you can see that the same settings from Chapter 6 are shown, with two additional properties:
By setting the value of the org.quartz.jobStore.is Clustered property to true, you are telling the Scheduler instance that it is participating in a cluster. This property is used throughout the scheduling framework to modify the default behavior when operating in a clustered environment.
The org.quartz.jobStore.clusterCheckinInterval property defines the frequency (in milliseconds) with which the Scheduler instance checks in with the database. The Scheduler checks to see if other instances haven't checked in as they should; that could indicate a failed Scheduler instance whereby the current Scheduler would take over any recoverable jobs that failed in progress. Upon check-in, the Scheduler also updates its own state record.
The smaller the clusterCheckinInterval is, the more often the Scheduler nodes check for failed Scheduler instances. The default value is set to 15000 (or 15 seconds).
Configuring the JobStore Data Source
Because you must use a JDBC JobStore (either JobStoreTX or JobStoreCMT) for clustering, you also need to configure a nonmanaged data source (by "nonmanaged," we mean that the data source is not managed by an application server). Look at Listing 11.1 for an example of setting up a nonmanaged data source for the JobStoreTX. Look at Chapter 6 for a list of available properties and their allowed values.
Loading the Database with Scheduler Information
As with all Quartz applications that use a database for Job storage, you must load job information into the database. We talked about the various methods of accomplishing this in Chapter 6.
One of the ways is to write a stand-alone Quartz application that is configured to use the database via one of the JDBC JobStores, creates a Scheduler instance, and schedules all of the job and trigger information. You might give this application the capability to clear the job information from the database by passing an argument into the command line. The problem with this approach is that maintaining the database becomes very cumbersome.
Another approach would be to use a query tool that comes with your specific RDBMS and load the information yourself manually. This makes updates and deletion quite easy, but it can be problematic loading the data for the first time unless you know what you're doing; we highly discourage this.
Some find using the Quartz Web Application, discussed in Chapter 13," Quartz and Web Applications," to be a convenient method. Managing job information is easy and can even be done by nontechnical resources. See Chapter 13 for information on the Quartz Web Application and, if you choose, for information on integrating Quartz into your own GUI application.
Scheduling in the Enterprise
Getting Started with Quartz
Cron Triggers and More
JobStores and Persistence
Implementing Quartz Listeners
Using Quartz Plug-Ins
Using Quartz Remotely
Using Quartz with J2EE
Quartz and Web Applications
Using Quartz with Workflow
Appendix A. Quartz Configuration Reference