最新quartz框架介绍.docx_第1页
最新quartz框架介绍.docx_第2页
最新quartz框架介绍.docx_第3页
最新quartz框架介绍.docx_第4页
最新quartz框架介绍.docx_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

21Quartz任务调度框架胡顺强 2013-01-11目录一,概述(Quartz介绍)3二,相关术语3三,Quartz体系结构31,Job42,JobDetail43,Trigger54,Scheduler6四,Quartz作业管理和存储7五,Quartz集群8六,Quartz简单应用(demo详解)10七,Quartz的优势13八,Quartz的缺陷14九,支付系统自动DDN预授权确认应用14十,附录16一,概述(Quartz介绍)Quartz是一个完全由java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,控制作业的运行时间。其中quartz集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。最新版本:Quartz 2.1.2使用环境:J2EE、J2SE参考资料:用途:定时执行任务,如:定时发邮件,定时发传真,定时发SMS等等定时任务。二,相关术语术语描述集群服务器各节点组合故障切换当一个节点正在执行一个或者多个任务失败的时候。当其出现故障导致任务执行失败的时候,其他的节点会检测到并且标识在失败节点上正在进行的数据库中的任务负载平衡负载平衡是自动完成的,集群的每个节点会尽快触发任务。当一个触发器的触发时间到达时,第一个节点将会获得任务(通过锁定),成为执行任务的节点三,Quartz体系结构Quartz框架主要核心组件包括调度器、触发器、作业。调度器作为作业的总指挥,触发器作为作业的操作者,作业为应用的功能模块。其关系如下图所示:Job为作业的接口,为任务调度的对象;JobDetail用来描述Job的实现类及其它相关的静态信息;Trigger为作业的定时管理工具,一个Trigger只能对应一个作业实例,而一个作业实例可对应多个触发器;Scheduler为定时任务容器,为quartz最上层的东西,它提携了所有触发器和作业,使它们协调工作,每个Scheduler都存有JobDetail和Trigger的注册,一个Scheduler中可以注册多个JobDetail和多个Trigger。1,Job是一个接口,只有一个方法void execute(JobExecutionContext context),被调度的作业(类)需实现该接口中execute()方法,JobExecutionContext类提供了调度上下文的各种信息。每次执行该Job均重新创建一个Job实例,如:public class DDNJob implements Jobpublic void execute(JobExecutionContext arg0) throws JobExecutionException / TODO Auto-generated method stubperform();public void perform() /执行报表统计入口函数 /业务逻辑 System.out.println(自动DDN预授权开始执行-执行时间:+new Date(); 注:DDNJob类为需要定时执行的类,execute为定时执行的方法。一个定时任务对应一个Job实现类。2,JobDetailQuartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。JobDetail 用来保存我们作业的详细信息。一个JobDetail可以有多个Trigger,但是一个Trigger只能对应一个JobDetail 示例:1. JobDetailjobDetail=newJobDetail(myJob,myGroup,DDNJob.class)2. 说明:3. myJob:job名4. myGroup:job组(为null时,使用缺省的组sched.DEFAULT_GROUP)5. DDNJob.class:要被执行的Java类。运用spring集成的MethodInvokingJobDetailFactoryBean时spring能自动生成符合quartz要去的JobDetail。Spring中applicationContext.xml配置如下: (并发执行) 3,Trigger是一个类,描述触发Job执行的时间触发规则。主要有SimpleTrigger和 CronTrigger这两个子类。当仅需触发一次或者以固定时间间隔周期执行,SimpleTrigger是最适合的选择;而CronTrigger则 可以通过Cron表达式定义出各种复杂时间规则的调度方案:如每早晨9:00执行,周一、周三、周五下午5:00执行等;Spring中applicationContext.xml配置如下: SimpleTrigger使用示例/ Initiate SimpleTrigger with its name and group nameSimpleTrigger simpleTrigger = new SimpleTrigger(simpleTrigger,triggerGroup1);/ set its start up timesimpleTrigger.setStartTime(new Date(System.currentTimeMillis();/ set the interval, how often the job should run (10 seconds here) simpleTrigger.setRepeatInterval(10000);/ set the number of execution of this job, set to 10 times.simpleTrigger.setRepeatCount(10);.通过Spring配置,jobDetail为配置的Job描述,startDelay为系统启动执行延迟时间,repeatCount为调用次数,repeatInterval为Job触发时间间隔。 CronTrigger使用示例:./ Initiate CronTrigger with its name and group nameCronTrigger cronTrigger = new CronTrigger(cronTrigger,triggerGroup2);try / setup CronExpression CronExpression cexp = new CronExpression(0/5 * * * * ?);/ Assign the CronExpression to CronTrigger cronTrigger.setCronExpression(cexp); catch (Exception e) e.printStackTrace();.通过Spring配置,jobDetail为配置的Job描述,cronExpression为Job的运行规则,具体见附录部分内容。 4,SchedulerScheduler负责管理Quartz的运行环境,Quartz它是基于多线程架构的,它启动的时候会初始化一套线程,这套线程会用来执行一些预置的作业。Trigger和JobDetail可以注册到Scheduler中;Scheduler可以将Trigger绑定到某一JobDetail中,这样当Trigger触发时,对应的Job就被执行。Scheduler拥有一个SchedulerContext,它类似于ServletContext,保存着Scheduler上下文信息,Job和Trigger都可以访问SchedulerContext内的信息。Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。 应用示例: SchedulerFactory schedulerFactory = new StdSchedulerFactory(); / Retrieve a scheduler from schedule factory Scheduler scheduler = schedulerFactory.getScheduler(); / schedule a job with JobDetail and Trigger scheduler.scheduleJob(jobDetail, simpleTrigger); / start the scheduler scheduler.start(); Spring中applicationContext.xml配置: !- - 其中,dataSource为数据源配置,triggers为触发器列表配置,可以同时包含多个trigger,configLocation为quartz配置文件perties加载路径。四,Quartz作业管理和存储作业一旦被调度,调度器需要记住并且跟踪作业和它们的执行次数。如果你的作业是30分钟后或每30秒调用,这不是很有用。事实上,作业执行需要非常准确和即时调用在被调度作业上的execute()方法。Quartz通过一个称之为作业存储(JobStore)的概念来做作业存储和管理。Quartz提供两种基本作业存储类型。第一种类型叫做RAMJobStore,它利用通常的内存来持久化调度程序信息。这种作业存储类型最容易配置、构造和运行。对许多应用来说,这种作业存储已经足够了。然而,因为调度程序信息是存储在被分配给JVM的内存里面,所以,当应用程序停止运行时,所有调度信息将被丢失。如果你需要在重新启动之间持久化调度信息,则将需要第二种类型的作业存储。第二种类型的作业存储实际上提供两种不同的实现,但两种实现一般都称为JDBC作业存储。两种JDBC作业存储都需要JDBC驱动程序和后台数据库来持久化调度程序信息。这两种类型的不同在于你是否想要控制数据库事务或这释放控制给应用服务器例如BEAs WebLogic或Jboss。(这类似于J2EE领域中,Bean管理的事务和和容器管理事务之间的区别)这两种JDBC作业存储是: JobStoreTX:当你想要控制事务或工作在非应用服务器环境中时使用 JobStoreCMT:当你工作在应用服务器环境中和想要容器控制事务时使用。JDBC作业存储为需要调度程序维护调度信息的用户而设计。例如:配置文件perties配置如下org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX五,Quartz集群虽然单个Quartz实例能给予你很好的Job调度能力,但它不能满足典型的企业需求,如可伸缩性、高可靠性满足。假如你需要故障转移的能力并能运行日益增多的 Job,Quartz集群势必成为你应用的一部分了。使用 Quartz 的集群能力可以更好的支持你的业务需求,并且即使是其中一台机器在最糟的时间崩溃了也能确保所有的 Job 得到执行。一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。图:表示了每个节点直接与数据库通信,若离开数据库将对其他节点一无所知因为Quartz 集群依赖于数据库,所以必须首先创建Quartz数据库表。Quartz 包括了所有被支持的数据库平台的 SQL 脚本。在 /docs/dbTables 目录下找到那些 SQL 脚本,根据不同的数据库SQL脚本不同,如下为quartz-1.8.5版本oracle数据库的sql脚本,共12张表。以下为数据库表列表及说明:表名描述QRTZ_BLOG_TRIGGERSTrigger作为Blob类型存储(用于Quartz用户用JDBC创建他们自己定制的Trigger类型,JobStore 并不知道如何存储实例的时候)QRTZ_CALENDARS以Blob类型存储Quartz的Calendar信息QRTZ_CRON_TRIGGERS存储Cron Trigger,包括Cron表达式和时区信息QRTZ_FIRED_TRIGGERS存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息QRTZ_JOB_DETAILS存储每一个已配置的Job的详细信息QRTZ_LOCKS存储程序的非观锁的信息(假如使用了悲观锁)QRTZ_PAUSED_TRIGGER_GRPS存储已暂停的Trigger组的信息QRTZ_SCHEDULER_STATE存储少量的有关 Scheduler的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)QRTZ_JOB_LISTENERS存储有关已配置的 JobListener的信息QRTZ_SIMPLE_TRIGGERS存储简单的 Trigger,包括重复次数,间隔,以及已触的次数QRTZ_SIMPROP_TRIGGERSQRTZ_TRIGGERS存储已配置的 Trigger的信息Spring中perties配置quartz集群功能:org.quartz.jobStore.isClustered = true org.quartz.jobStore.clusterCheckinInterval =20000 六,Quartz简单应用(demo详解)1,创建Job服务类(需要定时执行的任务)package mon.autoDDN;import java.util.Date;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;public class DDNJob implements Jobpublic void execute(JobExecutionContext arg0) throws JobExecutionException / TODO Auto-generated method stubperform();public void perform() /执行报表统计入口函数 /业务逻辑 System.out.println(自动DDN预授权开始执行-执行时间:+new Date(); 2,配置文件 perties配置文件配置#=# Configure Main Scheduler Properties #=org.quartz.scheduler.instanceName = DefaultQuartzSchedulerorg.quartz.scheduler.instanceId = AUTO#=# Configure ThreadPool #=org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount = 10org.quartz.threadPool.threadPriority = 5org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true#=# Configure JobStore #=org.quartz.jobStore.misfireThreshold = 60000org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegateorg.quartz.jobStore.tablePrefix = QRTZ_org.quartz.jobStore.maxMisfiresToHandleAtATime=10org.quartz.jobStore.isClustered = true org.quartz.jobStore.clusterCheckinInterval =20000 jdbc数据库连接配置文件perties配置:jdbc.driverClassName=oracle.jdbc.driver.OracleDriverjdbc.url=jdbc:oracle:thin:11:1521:HCCDEVjdbc.username=mpmjdbc.password=mpm applicationContext.xml配置文件:classpath:perties !- - 七,Quartz的优势假如你需要故障转移的能力并能运行日益增多的 Job,Quartz集群势必成为你应用的一部分了,使用 Quartz 的集群能力可以更好的支持你的业务需求,并且即使是其中一台机器在最糟的时间崩溃了也能确保所有的 Job 得到执行。 一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。总结: Quartz能完成较为复杂的定时任务 Quartz的集群功能保证了任务可靠、高效的正常执行,当集群中其中的一个节点出问题时,另外的节点接手任务,继续工作。 Quartz功能强大但配置较为简单 无环境依赖性,java的普通应用均能使用八,Quartz的缺陷Quartz 实际并不关心你是在相同的还是不同的机器上运行节点。当集群是放置在不同的机器上时,通常称之为水平集群。节点是跑在同一台机器是,称之为垂直集群。对于垂直集群,存在着单点故障的问题。这对高可用性的应用来说是个坏消息,因为一旦机器崩溃了,所有的节点也就被有效的终止了。 当你运行水平集群时,时钟应当要同步,以免出现离奇且不可预知的行为。假如时钟没能够同步,Scheduler 实例将对其他节点的状态产生混乱。有几种简单的方法来保证时钟何持同步,而且也没有理由不这么做。最简单的同步计算机时钟的方式是使用某一个 Internet 时间服务器(Internet Time Server ITS)。Trigger配置文件更改时当数据库qrtz_cron_triggers中cron_expression未更改,则触发器的运行触发规则未改变。总结: 时间规则更改不方便,需同步更改数据库时间规则描述 Quartz集群当所有节点跑在同一台服务器上,当服务器崩溃时所有节点将终止,定时任务将不能正常执行 Quartz集群当节点不在同一台服务器上时,因时钟的可能不同步导致节点对其他节点状态的产生影响。九,支付系统自动DDN预授权确认应用A. 原方案:现MpmApp中自动DDN预授权是一个定时运行的线程,从启动应用开始线程sleep每12分钟线程运行一次,符合条件就执行预授权确认。运行条件: 自动DDN配置为“启动”(该配置为后台页面控制,该条件无异常情况都是启动状态) 当前时间在当天的21:00后(程序中涉及new Date()出来判断时间是否为21点后) 当天没有执行过”预授权确认“(程序中涉及new Date()出来判断当天时间)都满足条件则自动DDN就执行,并记录标识,否则不执行。图解:问题描述 通过定时线程,在正常情况下运行正常,正常时间为21:00-21:12分之间。当特殊情况出现在第2和第3步,第2步new一个时间比较了,当前时间为当天23:59,判断通过。第3步new一个时间比较了,当前时间为00:01,这个已经是第二天,当天预授权没有执行过。判断通过。所以在00:01这个时间自动DDN预授权就跑了,导致第二天的21点自动DDN不执行。 毎12分钟线程运行一次,消耗cpu资源。B. 新方案使用quartz定时器定时执行检查工作,每天定时执行两次,分别在21:00和22:00,当21:00正常执行时22:00不执行,当21:00未正常执行时22:00执行。如下图所述:为了保证信用卡自动DDN预授权确认正常执行,定时器每天定时执行两次,当未有执行记录时预授权正常执行。十,附录 附:cronExpression表达式解释:0 0 12 * * ?-在每天中午12:00触发0 15 10 ? * *-每天上午10:15 触发0 15 10 * * ?-每天上午10:15 触发0 15 10 * * ? *-每天上午10:15 触发0 15 10 * * ? 2005-在2012年中的每天上午10:15 触发0 * 14 * * ?-每天在下午2:00至2:59之间每分钟触发一次0 0/5 14 * * ?-每天在下午2:00至2:59之间每5分钟触发一次0 0/5 14,18 * * ?-每天在下午2:00至2:59和6:00至6:59之间的每5分钟触发一次0 0-5 14 * * ?-每天在下午2:00至2:05之间每分钟触发一次0 10,44 14 ? 3 WED-每三月份的星期三在下午2:10和2:44时触发0 15 10 ? * MON-FRI-从星期一至星期五的每天上午10:15触发0 15 10 15 * ?-在每个月的每15天的上午10:15触发0 15 10 L * ?-在每个月的最后一天的上午10:15触发0 15 10 ? * 6L-在每个月的最后一个星期五的上午10:15触发0 15 10 ? * 6L 2002-2005-在2002, 2003, 2004 and 2005年的每个月的最后一个星期五的上午10:15触发0 15 10 ? * 6#3-在每个月的第三个星期五的上午10:15触发0 0 12 1/5 * ?-从每月的第一天起每过5天的中午12:00时触发0 11 11 11 11 ?-在每个11月11日的上午11:11时触发. 通配符说明:*可用在所有字段中,表示对应时间域的每一个时刻,例如,*在分钟字段时,表示“每分钟”?该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符-表示区间。例如 在小时上设置 10-12,表示 10,11,12点都会触发,表示指定多个值,例如在周字段上设置 MON,WED,FRI 表示周一,周三和周五触发/x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/yL该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值X,则表示“这个月的最后X天”,例如,6L表示该月的最后星期五W该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日期范围#该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发 配置perties文件说明:#调度标识名 集群中每一个实例都必须使用相同的名称 org.quartz.scheduler.instanceName = scheduler#ID设置为自动获取 每一个节点必须不同 org.quartz.scheduler.instanceId = AUTO#数据保存方式为持久化 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX#数据库平台 org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate #数据库别名 随便取org.quartz.jobStore.dataSource = myXADS#表的前缀 org.quartz.jobStore.tablePrefix = QRTZ_#设置为TRUE不会出现序列化非字符串类到 BLOB 时产生的类版本问题 org.quartz.jobStore.useProperties = true#加入集群 org.quartz.jobStore.isClustered = true#调度实例失效的检查时间间隔 org.quartz.jobStore.clusterCheckinInterval = 20000#容许的最大作业延长时间 org.quartz.jobStore.misfireThreshold = 60000#ThreadPool 实现的类名 org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool#线程数量 org.quartz.threadPool.threadCount = 10#线程优先级 org.quartz.threadPool.threadPriority = 5#自创建父线程 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true#设置数据源org.quartz.dataSource.myXADS.jndiURL = CT#jbdi类名 org.quartz.dataSource.myXADS.java.naming.factory.initial = weblogic.jndi.WLInitialContextFactory #URLorg.quartz.dataSource.myXADS.vider.url = t3:/localhost:7001 数据库表简单说明:表qrtz_job_details: 保存job详细信息,该表需要用户根据实际情况初始化job_name:集群中job的名字,该名字用户自己可以随意定制,无强行要求job_group:集群中job的所属组的名字,该名字用户自己随意定制,无强行要求job_class_name:集群中个note job实现类的完全包名,quartz就是根据这个路径到classpath找到该job类is_durable:是否持久化,把该属性设置为1,quartz会把job持久化到数据库中job_data:一个blob字段,存放持久化job对象表qrtz_triggers: 保存trigger信息trigger_name: trigger的名字,该名字用户自己可以随意定制,无强行要求trigger_group:trigger所属组的名字,该名字用户自己随意定制,无强行要求job_name: qrtz_job_details表job_name的外键job_group: qrtz_job_details表job_group的外键trigger_state:当前trigger状态,设置为ACQUIRED,如果设置为WAITING,则job不会触发trigger_cron:触发器类型,使用cron表达式表qrtz_cron_triggers:存储cron表达式表trigger_name: qrtz_triggers表trigger_name的外键trigger_group: qrtz_triggers表trigger_group的外键cron_expression:cron表达式表qrtz_scheduler_state:存储集群中note实例信息,quartz会定时读取该表的信息判断集群中每个实例的当前状态instance_name:之前配置文件中org.quartz.scheduler.instanceId配置的名字,就会写入该字段,如果设置为AUTO,quartz会根据物理机名和当前时间产生一个名字last_checkin_time:上次检查时间checkin_interval:检查间隔时间Quartz插件:需要实现org.quartz.spi.SchedulerPlugin借口,有#initialize,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论