Quartz Job Scheduling Framework[翻译]第六章. Job 存储和持久化 (第五部分)

十. 使用数据库存储 Scheduler 信息

·加载 Job 到数据库中

在前面有一节,"使用内存存储 Scheduler 信息",我们谈到关于在使用 RAMJobStore 时如何加载 Job 和 Trigger 信息到内存中。那么  Job 和 Trigger 又是如何加载到数据库中的呢?存在以下几个方法把 Job 信息存入到数据库:

    · 在你的程序中加入 Job 信息

    · 使用 JobInitializationPlugin

    · 使用 Quartz Web 应用程序

我们在前面的 RAMJobStore 章节中讨论过前面两种途径。当它们用于 JDBC JobStore 时,并没有多大不同,只些许例外。首先,你需要知道,当使用这两个方法式,Job 信息是在数据库中的。甚至在你停止了程序后,这些信息仍然保留在数据库中。甚至是你不在你的程序中使用 JobInitializationPlugin 时,这些信息也还在数据库中。基于这一点,它是会从数据库中找寻 Job 信息。第八章涵盖了 JobInitializationPlugin 和常用的 Quartz 插件。

最后一种方法可能是最有意思的。我们还没有谈论到 Quartz Web 应用,但是我们在第十三章 "Quartz 和 Web 应用" 是这么做的。在现在呢,你应当知道 Quartz Web 应用是一个基于浏览器的 GUI 程序,它是设计用来管理 Quartz Scheduler。它是由 Quartz 用户设计的,它为加入 Job 和 Trigger、启动和暂停 Scheduler 和发布其他功能呈现了一个相当好的界面。

通过 SQL 工具加载 Job最后还有一种能用于加载 Job 信息的方法,但仅在这儿提一下,并不鼓励你去尝试它。这种方法是使用本地 SQL 直接操作 Quartz 表来尝试加载和/或修改信息。使用本地查询工具来加入 Job 信息到数据库中只在少数时候这样做,但是很容易破坏数据进而导致所有 Job 不能正确运行。无论如何应尽力避免用这种方法。

十一. 使用 JobStoreCMT

许多我们在前面章节对 JobStoreTX 所说的和做的对于另一版本的 JDBC JobStoreJobStoreCMT 来也是适用的。再说,也没说所有,这不足为奇,因为它们都是 JobStore 类型,它们都是设计成用 JDBC 来与关系型数据库交互。也都是继承自共同的基类。

JobStoreCMT 被设计成参与到容器的事物边界内。这意味着容器创建一个 JTA 事物并使之对于 JobStore 可用。Quartz 与 JobStore 的交互保持在这个事物中。假如出现任何问题,Quartz 能给容器一个信号,它希望通过调用事物的 setRollbackOnly() 使事物回滚。

·配置 JobStoreCMT

同之前的 JobStoreTXRAMJobStore 一样,要使用 JobStoreCMT 的第一步是告知 Scheduler 你打算用 JobStoreCMT。和以前类似,也是通过在 quartz.properties 文件中设置 JobStore 类属性来做到这一点的:

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT

如果属性文件中存在 RAMJobStore 行,要确保移除了它。

·配置 DriverDelegate

你也是需要像为 JobStoreTX 所做的那样选择 DriverDelegate。Quartz 依靠一个 DriverDelegate 与给定的数据库通信。代理负责了与 JDBC Driver,也就是数据库的所有通信。

回到表 6.2 中的 DriverDelegate 列表,并基于你的数据库平台和环境选择一个。要加 MS SQLServer 代理到 quart.properties 文件,那就加入下一行:

org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.MSSQLDelegate

你可以使几个属性来帮助调整 JobStoreCMT。表 6.5 列举了全部设置项。

表 6.5. 用于设置 JobStoreCMT 的配置属性
属性 默认值
org.quartz.jobStore.driverDelegateClass  
描述:能够理解不同数据库系统中特定方言的驱动代理
org.quartz.jobStore.dataSource  
描述:这是一个用于 quartz.properties 文件的数据源配置块的名字。
org.quartz.jobStore.nonManagedTXDataSource  
描述:
JobStoreCMT 需要一个(第二个) 数据源,它所包含的连接不作为容器管理事特的一部分。 这个属性值必须是一个定义在配置属性文件中的数据源的名字。这个数据源必须包含非容器管理事物(non-CMT) 连接,换名话说就是, 它产生的连接可让 Quartz 直接合法的调用它的 commit()rollback() 方法。
org.quartz.jobStore.tablePrefix QRTZ_
描述:这是指定给 Scheduler 的一套数据库表名的前缀。Schedulers 在指定了不同前缀时可在同一数据库中使用不同的表。
org.quartz.jobStore.useProperties False
描述:"use properties" 标记指示着持久性 JobStore 所有在 JobDataMap 中的值都是字符串,因此能以 名-值 对的形式存储,而不用让更复杂的对象以序列化的形式存入 BLOB 列中。这样会更方便,因为让你避免了发生于序列化你的非字符串的类到 BLOB 时的有关类版本的问题。
org.quartz.jobStore.misfireThreshold 60000
描述:在 Trigger 被认为是错过触发之前,Scheduler 还容许 Trigger 通过它的下次触发时间的毫秒数(译者注:据原文翻译,真的不好理解,实际效果可参看:http://www.blogjava.net/Unmi/archive/2007/10/23/153413.html 我在评论中的实验)。默认值(假如你未在配置中存在这一属性条目) 是 60000(60 秒)。这个不仅限于 JDBC-JobStore;它也可作为 RAMJobStore 的参数
org.quartz.jobStore.isClustered False
描述:设置此为 true 来打开集群特性。假如你有多个 Quartz 实例使用同一套数据库表时这个属性必须设置为 true。
org.quartz.jobStore.clusterCheckinInterval 15000
描述:设置一个频度(毫秒),用于实例报告给集群中的其他实例。这会影响到侦测失败实例的敏捷度。它只用于设置了 isClustered 为 true 的时候。
org.quartz.jobStore.maxMisfiresToHandleAtATime 20
描述: 这是 JobStore 能处理的错过触发的 Trigger 的最大数量。处理太多(超过两打) 很快会导致数据库表被锁定够长的时间,这样就妨碍了触发别的(还未错过触发) trigger 执行的性能。
org.quartz.jobStore.dontSetAutoCommitFalse False
描述:设置这个参数为 true 则告诉 Quartz 不要调用从 DataSource 获取到的连接的 setAutoCommit(false) 方法. 这在少些情况下是有帮助的、例如你有一个驱动在已是 off 时又调用了这个方法会有所抱怨. 这个属性默认为 false,因为多数驱动需要调用 setAutoCommit(false) 方法。
org.quartz.jobStore.selectWithLockSQL SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE
描述:这必须是一个从 LOCKS 表查询一行并对这行记录加锁的 SQL 语句。假如未设置,默认值就是 SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE,这能在大部分数据库上工作。{0} 会在运行期间被前面你配置的 TABLE_PREFIX 所替换。
org.quartz.jobStore.dontSetNonManagedTX
ConnectionAutoCommitFalse
 False
描述:这个属性同 org.quartz.jobStore.dontSetAutoCommitFalse, 只是它还可以应用于不受管理事物的数据源(nonManagedTXDataSource)。
org.quartz.jobStore.txIsolationLevelSerializable False
描述:值为 True 时告诉 Quartz (当使用 JobStoreTXCMT 时) 调用 JDBC 连接的 setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE) 方法。这能助于防止某些数据库在高负荷和长事物时的锁超时。
org.quartz.jobStore.txIsolationLevelReadCommitted False
描述:当设置为 true 时,这一属性告诉 Quartz 调用不受管理的 JDBC 连接的 setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED) 方法。这能助于防止某些数据库(如 DB2) 在高负荷和长事物时的锁超时。

本文链接 https://yanbin.blog/quartz-job-scheduling-framework-6-5/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

4 Comments
Inline Feedbacks
View all comments
BEAU
BEAU
12 years ago

楼主神功盖世,技压群雄,千秋万代,一统江湖!

何岩
15 years ago

请问:如何让quartz不去执行错过的任务,而直接执行下一次的任务,

就算我把org.quartz.jobStore.misfireThreshold 设置为最小的1

quartz也会立即执行一次错过的任务,但我想让quartz不要执行任何错过的任务,如何实现,谢谢楼主

隔叶黄莺
15 years ago

看这个

http://www.blogjava.net/Unmi/archive/2007/10/23/153413.html

你可以照着做个测试看看

何岩
15 years ago

谢谢楼主回复,我已经看了在第一篇中评论中的例子,理解了org.quartz.jobStore.misfireThreshold的意思

但我要问的问题不是您例子里要解释的意思

我的问题是:

比如

我建立了一个cronTrigger,cron表达式为:0 * * * * ?

就是在每分钟的0秒触发。

org.quartz.jobStore.misfireThreshold=1000 #1秒

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX

下面是我的操作流程:

1)我在10:00:00启动程序,它执行了一次并且执行用时为1微妙,下一次的执行时间应该为10:01:00,

2)在10:00:20这个时刻我手动停掉程序,

3)在10:15:23这个时刻我又启动程序,这时程序立即执行了一次丢失任务。但这个任务是我不想要的,如何不让它执行??

我已经把misfireThreshold=1000也就是说 10:15:23这个时刻往前推1秒时没有丢失任务的 但为什么还是会执行一次丢失任务??

请问楼主知道如何配置能不让其执行丢失任务吗???

多谢!!