提示:本文中部分内容图片节选自互联网,无意冒犯。如有侵权请私信联系作者即刻删除、更改。
简介
JobStore接口负责记录Scheduler的所有工作数据:Job,Trigger,Calendar等。接口规定了大量操作它们的方法。一般而言我们代码编辑的层次只到达Scheduler接口,其他的配置为了方便都存放在配置文件中。
前边提到过Quartz符合企业级规范,并且支持事务和集群。但是就目前看来好像并没有体现也没有与持久化、事务等相关的代码程序,这其实与JobStore有关。Quartz中有两种存储任务的方式,一种是内存,另外一种是数据库。 在Quartz中内存存储方式对应了JobStore中RAMJobStore实现类,而数据库的存储方式则比较复杂,由于它们存在的包名为jdbc,所以它们又被统称为JDBCJobStore。如下为几个实现的数据库存储方式的JobStore:
- JobStoreCMT
用于提供容器管理事务的环境应用程序服务器。如果容器没有提供管理事务的的容器则将由此类自己管理。 - JobStoreTX
用于独立运行环境,提交和回滚事务都有此类处理。
RAMJobStore
Quartz中默认使用RAMJobStore,此时的任务和触发器信息运行的信息直接存储在内存中。RAMJobStore是最简单的JobStore,由于程序的数据是直接在存储中存取,所以性能较高。它的缺点是,当你的应用结束(或者崩溃、重启)时,所有存储在内存中的数据都会丢失。对于简单的应用或者没有任务记录状态的任务来讲可能无所谓,但是它并不符合企业级规范。
quartz.properities配置文件中与JobStore相关的配置如下:
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
JDBCJobStore
相比而下JDBCJobStore的实现则比较复杂,它可以通过 JDBC接口,将任务的运行数据保存在数据库中。要使用JDBCJobStore需要三步配置:
- 首先必须创建一组数据库表以供Quartz使用。可以在Quartz依赖包的docs/dbTables目录中找到创建相关表的SQL脚本示例。
需要注意的一点是,在这些脚本中,所有的表都以前缀QRTZ_开始(如表QRTZ_TRIGGERS和QRTZ_JOB_DETAIL)。当然前缀始可以修改的,只是需要配合quartz.properties文件中向的相关属性一起修改。这样做的好处在于对于多个调度程序实例,使用不同的前缀可能有助于创建多组表及组表的管理。我使用的版本为2.3此版本的SQL文件所在路径为:org\quartz\impl\jdbc-jobstore。如下图所示Quartz为常用的数据库都提供了SQL示例。
下表为每个表所代表的含义
- 创建表后,还需通过配置指定使用哪种JobStore用来管理事务,一般来说使用JobStoreTX就足够了。如果需要Quartz与其他事务(即J2EE应用程序服务器)一起工作,那么应该使用JobStoreCMT让应用程序服务器容器管理事务。
- 设置一个DataSource使JDBCJobStore可以从中获取与数据库的连接。DataSources在Quartz中可以使用两种不同的方法进行定义:
a) 通过配置quartz.properities文件,独立维护DataSource。
b) 使用正在运行的应用程序服务器管理的DataSource。
三步创建完成即代表Quartz的数据库存储模式搭建成功。下边以Quartz中的JobStoreTX为例展示一个简单的配置文件示例:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#配置方言driver
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#使用 quartz.properties,不使用默认配置
org.quartz.jobStore.useProperties:true
#表前缀配置JDBCJobStore
org.quartz.jobStore.tablePrefix = QRTZ_
#使用的DataSource的名称配置JDBCJobStore
org.quartz.jobStore.dataSource = idsDataSource
使用自定义DataSource版的配置如下:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#配置方言driver
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#使用 quartz.properties,不使用默认配置
org.quartz.jobStore.useProperties:true
#表前缀配置JDBCJobStore
org.quartz.jobStore.tablePrefix = QRTZ_
#使用的DataSource的名称配置JDBCJobStore
org.quartz.jobStore.dataSource = idsDataSource
#配置数据源
org.quartz.dataSource.idsDataSource.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.idsDataSource.URL:jdbc:mysql://localhost:3306/mysql?useUnicode=true&characterEncoding=utf8
org.quartz.dataSource.idsDataSource.user:root
org.quartz.dataSource.idsDataSource.password:1234
org.quartz.dataSource.idsDataSource.validationQuery=select 0 from dual
org.quartz.jobStore.driverDelegateClass的可选项有很多以下为常用的几个选项:
- org.quartz.impl.jdbcjobstore.StdJDBCDelegate
用于完全符合JDBC的驱动程序 - org.quartz.impl.jdbcjobstore.MSSQLDelegate
用于Microsoft SQL Server和Sybase - org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
用于PostgreSQL数据库 - org.quartz.impl.jdbcjobstore.WebLogicDelegate
用于WebLogic驱动程序 - org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
用于Oracle数据库 - org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate
用于Weblogic中使用的Oracle驱动程序
org.quartz.jobStore.useProperties(默认为false)可以将配置参数设置为true,以指示JDBCJobStore将JobDataMaps中的所有值都作为字符串,因此可以作为名称 - 值对存储而不是在BLOB列中以其序列化形式存储更多复杂的对象。从长远来看,这是更安全的,因为避免了将非String类序列化为BLOB的类版本问题。
JobStoreTX配置
JobStoreTX通过在每次操作(如添加jobs)后调用数据库连接上的commit()(或rollback())来管理所有事务。如果在独立应用程序中使用Quartz,或者在应用程序不使用JTA事务的情况下,可在Servlet容器中使用此JobStore。需要通过设置org.quartz.jobStore.class属性来选择JobStoreTX
#Driver代表了解不同数据库系统的特定“方言
#String类型,默认值为null,一般使用org.quartz.impl.jdbcjobstore.StdJDBCDelegate用于完全符合JDBC的驱动程序
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#DataSource的名称,可以是自定义的或者容器中包含的JDBC名称
org.quartz.jobStore.dataSource=myDataSource
#添加表前缀,默认表前缀为QRTZ_
org.quartz.jobStore.tablePrefix=QRTZ_
#标志指示JDBCJobStore,JobDataMaps中的所有值都将是“字符串”,
#因此可以将其存储为名称 - 值对,而不是以BLOB列的序列化形式存储更复杂的对象。
#这可以方便,因为您避免了将非String类序列化为BLOB时可能产生的类版本控制问题。
#boolean类型,默认值false
org.quartz.jobStore.useProperties=true
#用于设置失败临界值,或者临界时间。此选项的默认值为60s,默认配置的单位是毫秒。
#临界时间用于产生misfire失败的条件,即单线程执行定时任务,第一个任务的执行完后的结束时间减去第二个任务的开始时间即为临界时间。
#默认条件下临界时间大于60时, 第二个任务不会被执行。需注意:这个参数一般在多线程池条件下无效。
org.quartz.jobStore.misfireThreshold
#配置是否打开群集功能。如果您有多个Quartz实例使用同一组数据库表,
#则此属性必须设置为true,
#boolean类型默认值为false
org.quartz.jobStore.isClustered
#检测与群集的其他实例的频率(以毫秒为单位),默认值15000。影响检测失败实例的速度。
org.quartz.jobStore.clusterCheckinInterval
JobStoreCMT配置
JobStoreCMT可将自身事务管理交与运行Quartz的容器中的事务管理器管理。在尝试添加(或移除)jobs/Triggers之前,JTA事务必须进行中。
JobStoreCMT实际上需要使用两个数据源,一个是由应用程序服务器(通过JTA)管理的连接的事务,另一个数据源具有不参与全局(JTA)事务的连接。当应用程序使用JTA事务(例如通过EJB会话Bean)来执行其工作时可以选用JobStoreCMT。配置JobStoreCMT与上节中JobStoreTX类似:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
#配置DataSource的名称。对于JobStoreCMT,需要该DataSource包含能够参与JTA(例如容器管理的)事务的连接。
#这通常意味着DataSource将在应用程序服务器内部进行配置和维护,Quartz将通过JNDI获得一个句柄。
org.quartz.jobStore.dataSource
#JobStoreCMT需要一个(第二个)数据源,其中包含不会是容器管理事务的一部分的连接。
#此属性的值必须是配置属性文件中定义的DataSource的名称。此数据源必须包含非CMT连接,
#或换句话说,Quartz直接调用commit()和rollback()的合法连接。
org.quartz.jobStore.nonManagedTXDataSource
TerracottaJobStore
TerracottaJobStore用于在Terracotta服务器中存储任务运行时的调度信息。TerracottaJobStore比使用数据库来存储调度数据(通过JDBCJobStore)要好得多,而且提供了诸如负载平衡和故障切换之类的集群功能。
但是使用TerracottaJobStore需要考虑如何设置Terracotta服务器,特别是在启用功能的配置选项上,例如在磁盘上存储数据,使用fsync以及运行一系列的Terracotta服务器。TerracottaJobStore有两个必须做的配置:
org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore
org.quartz.jobStore.tcConfigUrl=localhost:9510
org.quartz.jobStore.tcConfigUrl用于配置主机和端口标识要连接的Terracotta服务器的位置。
另外还有一个可选的配置为org.quartz.jobStore.misfireThreshold用于设置失败临界值,或者临界时间。此选项的默认值为60s,默认配置的单位是毫秒。临界时间用于产生misfire失败的条件,即单线程执行定时任务,第一个任务的执行完后的结束时间减去第二个任务的开始时间即为临界时间。默认条件下临界时间大于60时, 第二个任务不会被执行。需注意:这个参数一般在多线程池条件下无效。