【Quartz】配置最简单的集群

  在许多情况,我们希望我们的定时任务是可靠的,不会因系统故障、机器宕机而导致某一笔定时任务不能按时运行。这种情况下,我们就需要为Quartz做个集群。

  最简单的情况,有两台机器或两个应用,同时维护一批定时任务,假如其中一个机器或应用出现问题,还有另外一个应用保底使用。

  代码与上一节【Quartz】将定时任务持久化到数据库基本一致,只列出不同的代码。

  在quartz.properties配置中设置需要集群,而集群节点的ID则由quartz自动生成

org.quartz.jobStore.isClustered = true
org.quartz.scheduler.instanceId = AUTO

  汇总后为

复制代码
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = myDS
# Cluster
org.quartz.jobStore.isClustered = true
org.quartz.scheduler.instanceId = AUTO

org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/ll?characterEncoding=utf-8
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password = 123456
org.quartz.dataSource.myDS.maxConnections = 5
复制代码

  注:俩应用的配置应相似,除了某些特殊配置,如线程池数量、实例ID

  这里启动两个应用,其中一个应用需要注册定时任务(这里注册的定时任务每30秒运行一次);另外一个应用因集群关系则无需注册定时任务。所以,启动类有所区别。

  应用A的Bootstrap类

 1 package No01简单的定时任务;
 2 
 3 import java.util.concurrent.TimeUnit;
 4 
 5 import org.quartz.CronScheduleBuilder;
 6 import org.quartz.JobBuilder;
 7 import org.quartz.JobDetail;
 8 import org.quartz.Scheduler;
 9 import org.quartz.SchedulerException;
10 import org.quartz.Trigger;
11 import org.quartz.TriggerBuilder;
12 import org.quartz.impl.StdSchedulerFactory;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15 
16 
17 public class Bootstrap {
18     private static Logger logger = LoggerFactory.getLogger(Bootstrap.class);
19 
20     public static void main(String[] args) {
21 
22         try {
23             // 获取Scheduler实例
24             Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
25             scheduler.start();
26 
27             // 具体任务
28             JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
29 
30             // 触发时间点
31             CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0,30 * * * * ? *");
32             Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
33                     .withSchedule(cronScheduleBuilder).build();
34 
35             // 交由Scheduler安排触发
36             scheduler.scheduleJob(job, trigger);
37             
38             try {
39                 TimeUnit.MINUTES.sleep(3);
40             } catch (InterruptedException e) {
41                 e.printStackTrace();
42             }
43 
44             // 关闭Scheduler
45             scheduler.shutdown();
46 
47         } catch (SchedulerException se) {
48             logger.error(se.getMessage(), se);
49         }
50     }
51 
52 }

  应用B的Bootstrap类

 1 package No01简单的定时任务;
 2 
 3 import org.quartz.Scheduler;
 4 import org.quartz.SchedulerException;
 5 import org.quartz.impl.StdSchedulerFactory;
 6 import org.slf4j.Logger;
 7 import org.slf4j.LoggerFactory;
 8 
 9 
10 public class Bootstrap {
11     private static Logger logger = LoggerFactory.getLogger(Bootstrap.class);
12 
13     public static void main(String[] args) {
14 
15         try {
16             // 获取Scheduler实例
17             Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
18             scheduler.start();
19 
20         } catch (SchedulerException se) {
21             logger.error(se.getMessage(), se);
22         }
23     }
24 
25 }

  现在,运行观察是否成功。先后启动应用A和应用B,运行并观察一段时间后,关闭应用A,继续观察。

  通过日志观察可见,首先定时任务有应用A执行,在应用A被关闭后,定时任务由应用B继续触发执行。

  注:这里观察到,似乎不是负载均衡,因为在应用A关闭后应用B才有机会运行。而我们理想中,应该是应用A与应用B互相补充、交替运行。这里主要因为只用了一个任务(只有一个触发器)做测试,如果运用多个触发器设置多个任务做测试,应用A与应用B互相补充、交替运行。

 

posted @ 2017-01-01 14:20  ngulc  阅读(721)  评论(0编辑  收藏  举报