以下将分别从Quartz架构简介、集群部署实践、Quartz监控、集群原理分析详解Quartz任务调度框架。 Quartz简介Quartz是Java领域最著名的开源任务调度工具,是一个任务调度框架,通过触发器设置作业的定时运行规则,来执行定时任务。其中quartz集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。 Quartz提供了极为广泛的特性如持久化任务,集群和分布式任务等。 其特点如下:
典型的使用场景,主要用来执行定时任务,例如:
Quartz架构简介Quartz框架主要核心组件包括: 1.Scheduler任务调度 是最核心的概念,需要把JobDetail和Trigger注册到scheduler中,才可以执行。
2.Job任务 其实Job是接口,其中只有一个execute方法,我们只需要 implements 此接口,重写 execute(*) 方法。 3.Trigger触发器 执行任务的规则;比如每天,每小时等。 一般情况使用SimpleTrigger,和CronTrigger,这些触发器实现了Trigger接口。或者 ScheduleBuilder 子类 SimpleScheduleBuilder和CronScheduleBuilder。 对于简单的时间来说,比如每天执行几次,使用SimpleTrigger。 对于复杂的时间表达式来说,比如每个月15日上午几点几分,使用CronTrigger以及CromExpression 类。 4.JobDetail任务细节 任务细节,Quartz执行Job时,需要新建个Job实例,但是不能直接操作Job类,所以通过JobDetail来获取Job的名称、描述信息。 调度器作为作业的总指挥,触发器作为作业的操作者,作业为应用的功能模块。 Quartz集群部署实践Quartz与Spring结合使用,Spring通过提供org.springframework.scheduling.quartz下的封装类对Quartz支持。 1.Quartz集群部署: Quartz集群中的每个节点是一个独立的Quartz应用,它又管理着其他的节点。该集群需要分别对每个节点分别启动或停止,不像应用服务器的集群,独立的Quartz节点并不与另一个节点或是管理节点通信。Quartz应用是通过数据库表来感知到另一应用。只有使用持久的JobStore才能完成Quqrtz集群。 基于Spring的集群配置: <> id='quartzScheduler' class='org.springframework.scheduling.quartz.SchedulerFactoryBean'> <> name='dataSource' ref='dataSource' /> <> name='quartzProperties'> Quartz监控Quartz实例的监控、操作以及动态部署Trigger. 1.Triggers监控: 2.JobDetails监控: Quartz集群原理分析1. Quartz集群数据库表 Quartz的集群部署方案在架构上是分布式的,没有负责集中管理的节点,而是利用数据库锁的方式来实现集群环境下进行并发控制。BTW,分布式部署时需要保证各个节点的系统时间一致。 Quartz数据库核心表如下:
2. Quartz线程模型 在Quartz中有两类线程:
任务执行线程:Quartz不会在主线程(QuartzSchedulerThread)中处理用户的Job。 Quartz把线程管理的职责委托给ThreadPool,一般的设置使用SimpleThreadPool。SimpleThreadPool创建了一定数量的WorkerThread实例来使得Job能够在线程中进行处理。WorkerThread是定义在SimpleThreadPool类中的内部类,它实质上就是一个线程。例如,CRM中配置如下: <> key='org.quartz.threadPool.class'>org.quartz.simpl.SimpleThreadPool <> key='org.quartz.threadPool.threadCount'>20 <> key='org.quartz.threadPool.threadPriority'>5 QuartzSchedulerThread调度主线程:QuartzScheduler被创建时创建一个QuartzSchedulerThread实例。 3.Quartz集群基于数据库锁的同步操作流程如下图所示: 一个调度器实例在执行涉及到分布式问题的数据库操作前,首先要获取QUARTZ_LOCKS表中对应的行级锁,获取锁后即可执行其他表中的数据库操作,随着操作事务的提交,行级锁被释放,供其他调度实例获取。集群中的每一个调度器实例都遵循这样一种严格的操作规程。 总结一下Quartz集群同步机制:每当要进行与某种业务相关的数据库操作时,先去QRTZ_LOCKS表中查询操作相关的业务对象所需要的锁,在select语句之后加for update来实现。例如,TRIGGER_ACCESS表示对任务触发器相关的信息进行修改、删除操作时所需要获得的锁。这时,执行查询这个表数据的SQL形如: select * from QRTZ_LOCKS t where t.lock_name='TRIGGER_ACCESS' for update 当一个线程使用上述的SQL对表中的数据执行查询操作时,若查询结果中包含相关的行,数据库就对该行进行ROW LOCK;若此时,另外一个线程使用相同的SQL对表的数据进行查询,由于查询出的数据行已经被数据库锁住了,此时这个线程就只能等待,直到拥有该行锁的线程完成了相关的业务操作,执行了commit动作后,数据库才会释放了相关行的锁,这个线程才能继续执行。 通过这样的机制,在集群环境下,结合悲观锁的机制就可以防止一个线程对数据库数据的操作的结果被另外一个线程所覆盖,从而可以避免一些难以觉察的错误发生。当然,达到这种效果的前提是需要把Connection设置为手动提交,即autoCommit为false。 本文标题:阿里P8架构师谈:Quartz调度框架详解、运用场景、与集群部署实践
转载请保留页面地址:http:///quartz-detailed-explanation.html |
|