Quartz-cluster最佳实践

1. 概述java

虽然单个Quartz实例能给予你很好的Job调度能力,但它不能知足典型的企业需求,如可伸缩性、高可靠性知足。假如你须要故障转移的能力并能运行日益增多的 Job,Quartz集群势必成为你应用的一部分了。使用 Quartz 的集群能力能够更好的支持你的业务需求,而且即便是其中一台机器在最糟的时间崩溃了也能确保全部的 Job 获得执行。mysql

2. 工做原理spring

一个 Quartz 集群中的每一个节点是一个独立的 Quartz 应用,它又管理着其余的节点。意思是你必须对每一个节点分别启动或中止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另外一其的节点或是管理节点通讯。Quartz 应用是经过数据库表来感知到另外一应用的。
图:表示了每一个节点直接与数据库通讯,若离开数据库将对其余节点一无所知
clip_image001sql

3. 环境搭建数据库

3.1. 建立quartz数据库表服务器

由于Quartz 集群依赖于数据库,因此必须首先建立Quartz数据库表。Quartz 包括了全部被支持的数据库平台的 SQL 脚本。在 <quartz_home>/docs/dbTables 目录下找到那些 SQL 脚本,这里的 <quartz_home> 是解压 Quartz 分发包后的目录。
这里采用的Quartz 1.6.0版本,总共12张表,不一样版本,表个数可能不一样。数据库为mysql,用tables_mysql_innodb.sql建立数据库表。app

3.2. 配置数据库链接池框架

1.配置jdbc.properties文件测试

clip_image003

2.配置applicationContext.xml文件3d

clip_image005

3.3. 配置集群节点的quartz.properties文件

clip_image007

说明:

org.quartz.scheduler.instanceName属性可为任何值,用在 JDBC JobStore 中来惟一标识实例,可是全部集群节点中必须相同。

org.quartz.scheduler.instanceId属性为 AUTO便可,基于主机名和时间戳来产生实例 ID。

org.quartz.jobStore.class属性为 JobStoreTX,将任务持久化到数据中。由于集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 做为 Job 存储;你不能在集群中使用 RAMJobStore。

org.quartz.jobStore.isClustered 属性为 true,你就告诉了 Scheduler 实例要它参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操做的默认行为。

org.quartz.jobStore.clusterCheckinInterval 属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。Scheduler 检查是否其余的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。经过检入操做,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (即15 秒)。

3.4. 建立Job服务类

clip_image009

说明:

由于Job须要持久化到数据库中,CustService必须实现Serializable接口,在这里只是简单打印一下日志。

可是这里有一个问题,若是咱们的这个CustService要继承其余的基类,并且基类并无实现序列化,那这个时候CustService仍然是没法持久化到数据库中的。因此咱们须要在CustService外面再加入一层业务引用,CustService当作一个对象注入到这个引用层里面,详细请看代码:

1 业务引用层MyBusiJob.java

clip_image011

2 实现序列化接口Job2

clip_image013

3 任务引导

clip_image015

3.5. 与Spring(2.0.8)集成

applicationContext-quartz.xml

clip_image017

说明:

1这个 MethodInvokingJobDetailFactoryBean ,原本应该采用org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean指定类和方法,可是直接使用会报java.io.NotSerializableException异常,这是由于这个类中的 methodInvoking 方法,是不支持序列化的,所以在把 QUARTZ 的 TASK 序列化进入数据库时就会抛错。并且目前最新版的spring也不支持这个问题。这里咱们使用spring 官方论坛通过修改的类替代,能够参考:

http://jira.springframework.org/browse/SPR-3797

3.6. 测试类

clip_image019

测试结果:

几个节点都带有 quartz 任务,此时只有一台 quartz 在运行,另几个节点上的 quartz 没有运行。

此时手动 shutdown 那台运行 QUARTZ ,过了 7 秒左右,另外一个节点的 quartz 自动监测到了集群中运行着的 quartz 的 instance 已经 shutdown ,所以 quartz 集群会自动把任一台可用的APP 上启动起一个 quartz job 的任务。

下面两种图片是quartz-cluster正常运行下的任务分发

环境:

WebLogic 10.3.5 + Redhat 5.6 + Quartz 1.6.0 + Spring 2.0.8

clip_image021

clip_image023

4. 部署

有两点须要注意:

1 集群配置文件quartz.properties部署的时候必需要一致

2 集群创建起来以后,若是运行过程当中须要修改quartz调度器的策略,例如:原来每5天执行一次任务,如今要改为每半个月执行一次,这个时候要修改全部的配置文件,而且要从新执行上述的数据库脚本!

相关文章
相关标签/搜索