最佳实践:利用Quartz实现任务调度的集群
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
软件体系最佳实践文档
第 1 页 共 10 页
最佳实践:利用Quartz实现任务调度的集群
分类:JAVA
作者:凡彬勇
日期:2012-06-20
导读:Quartz集群的实现
1. 任务调度为什么要实现集群
公众企业应用几乎都会碰到任务调度的需求,任务调度本身涉及到多线程并发、运行时间规则制定和解析、场景保持与恢复、线程池维护等诸多方面的工作。如果直接使用自定义线程这种刀耕火种的原始办法,开发任务调度程序是一项颇具挑战性的工作。Java开源的好处就是:领域问题都能找到现成的解决方案。
OpenSymphony所提供的Quartz自2001年发布版本以来已经被众多项目作为任务调度的解决方案,Quartz在提供巨大灵活性的同时并未牺牲其简单性,它所提供的强大功能使你可以应付绝大多数的调度需求。Quartz 在开源任务调度框架中的翘首,它提供了强大任务调度机制,难能可贵的是它同时保持了使用的简单性。Quartz 允许开发人员灵活地定义触发器的调度时间表,并可以对触发器和任务进行关联映射。此外,Quartz提供了调度运行环境的持久化机制,可以保存并恢复调度现场,即使系统因故障关闭,任务调度现场数据并不会丢失。此外,Quartz还提供了组件式的侦听器、各种插件、线程池等功能。
2. quartz集群的原理
一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。 软件体系最佳实践文档
第 2 页 共 10 页
图:表示了每个节点直接与数据库通信,若离开数据库将对其他节点一无所知
集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。目前集群只能工作在JDBC- Jobstore (JobStoreTX 或者JobStoreCMT)方式下,从本质上来说,是使集群上的每一个节点通过共享同一个数据库来工作的(Quartz通过启动两个维护线程来维护数据库状态实现集群管理,一个是检测节点状态线程,一个是恢复任务线程)。负载平衡是自动完成的,集群的每个节点会尽快触发任务。当一个触发器的触发时间到达时,第一个节点将会获得任务(通过锁定),成为执行任务的节点。故障切换的发生是在当一个节点正在执行一个或者多个任务失败的时候。当一个节点失败了,其他的节点会检测到并且标识在失败节点上正在进行的数据库中的任务。任何被标记为可恢复(任务详细信息的"requests recovery"属性)的任务都会被其他的节点重新执行。没有标记可恢复的任务只会被释放出来,将会在下次相关触发器触发时执行
3. quartz集群步骤
3.1. 创建Quartz数据库表
因为Quartz 集群依赖于数据库,所以必须首先创建Quartz数据库表。Quartz 包括了所有被支持的数据库平台的 SQL 脚本。在
这里采用的Quartz 1.8.5版本,总共12张表,不同版本,表个数可能不同。数据库为oracle,用tables_oracle.sql创建数据库表。 软件体系最佳实践文档
第 3 页 共 10 页
3.2. 配置数据库连接池 ,这里使用Spring+C3p0
在系统的全局配置文件中新增如下信息,我这里的全局配置文件是:config.properties
db.dialect=org.hibernate.dialect.Oracle9Dialect
db.driverClassName=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:@127.0.0.1:1521:feelview
ername=feelviewdata
db.password=paic1234
TescronExpression1=0 0/1 * ? * *
其中:TescronExpression1是定时器的crontab表达式(我这里配置的是每分钟跑一次),下面在配置CronTriggerBean的时候会使用到。关于crontab表达式的配置这里不做介绍,在quartz的官方文档有详细介绍
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
class="boPooledDataSource" destroy-method="close"> 第 4 页 共 10 页 name="idleConnectionTestPeriod">
3.3. 创建Job测试服务类
创建job接口,注意,因为Job需要持久化到数据库中,Job必须实现Serializable接口
public interface IJob extends Serializable{
/**
* 处理任务的核心函数
*
* @param cxt Spring 上下文
*/
void executeInternal();
}