介绍Quartz
介绍Quartz
Quartz是一个开源的任务调度系统,它能用来调度很多任务的执行。
运行环境????}
??}
如果用一个持久JobStore(在指南JobStore章节讨论),我们就应该注意在JobDataMap里放些什么,因为在它里面的对象将会被序列化,并且这些对象会因此产生一些class-versioning问题。明显的,标准Java类型应该是很安全的,但是,任何时候某人改变了一个你已经序列化的实例的类的定义时,我们就要注意不能够破坏兼容性了。在这个方面的进一步信息可以在Java Developer Connection Tech Tip: Serialization In The Real World里找到。我们能把JDBC-JobStore和JobDataMap放到一个模式里,在那里,只有简单类型和String型能被储存在Map里,从而消去任何以后的序列化问题。
Stateful vs. Non-Stateful Jobs
触发器也有与它们关联的JobDataMaps。假设我们有一个储存在调度器里被多个触发器关联的job,然而,对于每个独立的触发器,我想提供给job不同的数据输入,在这个时候,JobDataMaps就很有用了。
在job执行期间,JobDataMaps能够在JobExecutionContext里获得。JobDataMap融合在Trigger和JobDetail类里,JobDataMap里面的值能够利用key来更新。
以下例子显示,在job执行期间从JobExecutionContext里的JobDataMap得到数据:
public class DumbJob implements Job {
public DumbJob() {
????}
????public void execute(JobExecutionContext context)
??????throws JobExecutionException
????{
??????String instName = context.getJobDetail().getName();
??????String instGroup = context.getJobDetail().getGroup();
??????JobDataMap dataMap = context.getJobDataMap();??//?注意:不同于以前的例子
??????String jobSays = dataMap.getString("jobSays");
??????float myFloatValue = dataMap.getFloat("myFloatValue");
??????ArrayList state = (ArrayList)dataMap.get("myStateData");
??????state.add(new Date());
??????System.err.println("Instance " + instName + " of DumbJob says: " + jobSays);
????}
??}
StatefulJob
现在,关于job状态数据的一些附加要点:一个job实例能定义为"有状态的"或者"无状态的"。无状态的jobs仅当它们在被加入到调度器里时才存储JobDataMap。这就意味着,在jobs执行期间对JobDataMap里数据的任何改变都会丢失,下次执行时job将看不到这些数据。你可能会猜到,一个有状态的job就是它的反面例子-它的JobDataMap是在每次执行完job后再次储存的。一个缺点就是有状态的job不能够并发执行。换句话说,如果job是有状态的,一个触发器尝试触发这个已经执行了的job时,这个触发器就会等待直到这次执行结束。
用实现StatefulJob?接口来标记一个job是有状态的。
Job 'Instances'
我们能够创建一个单独的job类,并且通过创建多个JobDetails实例在调度器里储存很多它的“实例定义”,每个都有它自己的属性集和JobDataMap?,把它们都加入到调度器里。
当一个触发器触发时,与它关联的job就是通过配置在调度器上的JobFactory?来实例化的。默认的JobFactory?简单的调用在job类上的newInstance()方法,你可能想要创建自己的JobFactory实现来完成一些自己想要的事情,如:拥有应用程序的IoC或者DI容器进程/初始化job实例。
job的其他属性
这儿有一个其他属性的总结,这些属性是通过JobDetail对象为一个job实例定义的。
- "这个月的最后一个星期几"??例如:?"6L" means"这个月的最后一个星期五".?当我们用“L”时,不指明一个列表值或者范围是很重要的,不然的话,我们会得到一些意想不到的结果。
集群目前仅能和JDBC-JobStore(JobStoreTX或JobStoreCMT)一起工作,本质上是让集群的每个节点共享一个数据库来工作的。
Load-balancing是自动出现的,集群的每个节点尽可能快地触发job。当一个触发器触发时刻到了,第一个将获取触发器(并加锁)的节点就是将要触发它的节点。
Fail-over是一个节点正在执行一个或多个jobs时失败了出现的。当一个节点失败了,其他的节点就会在数据库里核查条件和鉴别jobs,这些是节点失败时记录到了数据库的。在恢复节点时,任何标记了恢复(JobDetail里的"requests recovery"属性)的jobs将会被再次执行,没有标记的将会简单地释放掉。
通过设置“org.quartz.jobStore.isClustered”属性来使用集群。在集群里每个实例应该用一样的quartz.properties文件。用到的异常也应该是一样的:不同线程池大小,不同“org.quartz.scheduler.instanceName”属性值。每个节点应该用唯一的instanceId。我们可以设置org.quartz.scheduler.instanceId的值为“AUTO”来达到这个目的。
不要在一个分离开的机器上运行集群,除非他们的时钟是用时钟同步服务同步过的。如果不熟悉怎样同步,参考:http://www.boulder.nist.gov/timefreq/service/its.htm
create index idx_qrtz_ft_job_group on qrtz_fired_triggers(JOB_GROUP);
?
????}
??}
如果用一个持久JobStore(在指南JobStore章节讨论),我们就应该注意在JobDataMap里放些什么,因为在它里面的对象将会被序列化,并且这些对象会因此产生一些class-versioning问题。明显的,标准Java类型应该是很安全的,但是,任何时候某人改变了一个你已经序列化的实例的类的定义时,我们就要注意不能够破坏兼容性了。在这个方面的进一步信息可以在Java Developer Connection Tech Tip: Serialization In The Real World里找到。我们能把JDBC-JobStore和JobDataMap放到一个模式里,在那里,只有简单类型和String型能被储存在Map里,从而消去任何以后的序列化问题。
Stateful vs. Non-Stateful Jobs
触发器也有与它们关联的JobDataMaps。假设我们有一个储存在调度器里被多个触发器关联的job,然而,对于每个独立的触发器,我想提供给job不同的数据输入,在这个时候,JobDataMaps就很有用了。
在job执行期间,JobDataMaps能够在JobExecutionContext里获得。JobDataMap融合在Trigger和JobDetail类里,JobDataMap里面的值能够利用key来更新。
以下例子显示,在job执行期间从JobExecutionContext里的JobDataMap得到数据:
public class DumbJob implements Job {
public DumbJob() {
????}
????public void execute(JobExecutionContext context)
??????throws JobExecutionException
????{
??????String instName = context.getJobDetail().getName();
??????String instGroup = context.getJobDetail().getGroup();
??????JobDataMap dataMap = context.getJobDataMap();??//?注意:不同于以前的例子
??????String jobSays = dataMap.getString("jobSays");
??????float myFloatValue = dataMap.getFloat("myFloatValue");
??????ArrayList state = (ArrayList)dataMap.get("myStateData");
??????state.add(new Date());
??????System.err.println("Instance " + instName + " of DumbJob says: " + jobSays);
????}
??}
StatefulJob
现在,关于job状态数据的一些附加要点:一个job实例能定义为"有状态的"或者"无状态的"。无状态的jobs仅当它们在被加入到调度器里时才存储JobDataMap。这就意味着,在jobs执行期间对JobDataMap里数据的任何改变都会丢失,下次执行时job将看不到这些数据。你可能会猜到,一个有状态的job就是它的反面例子-它的JobDataMap是在每次执行完job后再次储存的。一个缺点就是有状态的job不能够并发执行。换句话说,如果job是有状态的,一个触发器尝试触发这个已经执行了的job时,这个触发器就会等待直到这次执行结束。
用实现StatefulJob?接口来标记一个job是有状态的。
Job 'Instances'
我们能够创建一个单独的job类,并且通过创建多个JobDetails实例在调度器里储存很多它的“实例定义”,每个都有它自己的属性集和JobDataMap?,把它们都加入到调度器里。
当一个触发器触发时,与它关联的job就是通过配置在调度器上的JobFactory?来实例化的。默认的JobFactory?简单的调用在job类上的newInstance()方法,你可能想要创建自己的JobFactory实现来完成一些自己想要的事情,如:拥有应用程序的IoC或者DI容器进程/初始化job实例。
job的其他属性
这儿有一个其他属性的总结,这些属性是通过JobDetail对象为一个job实例定义的。
- "这个月的最后一个星期几"??例如:?"6L" means"这个月的最后一个星期五".?当我们用“L”时,不指明一个列表值或者范围是很重要的,不然的话,我们会得到一些意想不到的结果。
集群目前仅能和JDBC-JobStore(JobStoreTX或JobStoreCMT)一起工作,本质上是让集群的每个节点共享一个数据库来工作的。
Load-balancing是自动出现的,集群的每个节点尽可能快地触发job。当一个触发器触发时刻到了,第一个将获取触发器(并加锁)的节点就是将要触发它的节点。
Fail-over是一个节点正在执行一个或多个jobs时失败了出现的。当一个节点失败了,其他的节点就会在数据库里核查条件和鉴别jobs,这些是节点失败时记录到了数据库的。在恢复节点时,任何标记了恢复(JobDetail里的"requests recovery"属性)的jobs将会被再次执行,没有标记的将会简单地释放掉。
通过设置“org.quartz.jobStore.isClustered”属性来使用集群。在集群里每个实例应该用一样的quartz.properties文件。用到的异常也应该是一样的:不同线程池大小,不同“org.quartz.scheduler.instanceName”属性值。每个节点应该用唯一的instanceId。我们可以设置org.quartz.scheduler.instanceId的值为“AUTO”来达到这个目的。
不要在一个分离开的机器上运行集群,除非他们的时钟是用时钟同步服务同步过的。如果不熟悉怎样同步,参考:http://www.boulder.nist.gov/timefreq/service/its.htm
create index idx_qrtz_ft_job_group on qrtz_fired_triggers(JOB_GROUP);
?