JobStore持久化(第二篇)
12.使用JobStoreCMT持久化
之前讲的JobStoreTX中的大部分配置,都是适用于JobStoreCMT。
JobStoreCMT被设计用来参与到容器的事务边界内。这意味着容器创建一个JTA事务并使之对于JobStore可用。Quartz与JobStore的交互保持在这个事务中。假如出现问题,Quartz,Quartz 能给容器一个信号,它希望通过调用事物的 setRollbackOnly() 使事物回滚。
12.1 配置使用JobStoreCMT
首先告知Quartz使用JobStoreCMT来持久化
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
12.3 配置DriverDelegate
参考上面讲的JobStoreTX.
13.为JobStoreCMT配置数据源
与JonStoreTX一样,这里也需要一个DataSource才可以使用JobStoreCMT,但是JobStoreCMT需要两个数据源,而不是一个。
问:为什么JobStoreCMT需要两个Dataspurce呢??
答:JobStoreCMT 的原始作者,Jeffrey Wescott,设计 JobStoreCMT 使用一个标准的 JDBC 连接来做它“自己的工作”,同时,代表客户端(如部署 Job) 的工作在执行时是使用一个在容器控制之下有自身事物的 JDBC 连接。即使 Quartz 处在一个大事物中,这种设计也允许用户与 Quartz 交互,而无需 JobStoreCMT 非得使用应用服务器的事物管理器(例如,经由 UserTransaction) 在做自己内部工作时(如处理已错过执行的 Trigger) 来创建和终止事物。如果是 JobStoreCMT 使用 UserTransation 只给它配置一个数据源,从配置方面来看确实方便。然而,在相比于别的特性需求和改进的必要性时,作此变化并不会成为团队中首要的问题,因而 JobStoreCMT 还是继续要两个数据源。
13.1 配置不受管理的数据源
我们设置的不受管理的数据源与配置JobStoreTX的基本相同,知识额外加上一行如下的配置:
org.quartz.jobStore.nonManagedTXDataSource = atp
下面是不受管理的数据源配置信息:
org.quartz.dataSource.atp.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.atp.URL =
org.quartz.dataSource.atp.user = paas
org.quartz.dataSource.atp.password = paas
org.quartz.dataSource.atp.maxConnections = 10
我们配置不受管理的数据源并让JobStore知晓了这个nonManagedTXDataSource叫做“atp”。
13.2 配置受管理的DataSource
该数据源是一个受管理的数据源,它意味着在执行Scheduler操作时使用一个容器已经创建好的DataSource与数据库进行交互。当Quartz从Datasurce上取得连接后,在Quartz部署Job和Trigger时候应有一个JTA事务。例如,代码要求 Quartz 在 SessionBean 的一个方法上的事物描述符设置为 REQUIRED。另一个应用是客户端程序要通过使用 javax.transaction.UserTransaction 直接启动一个事物。
下面是样例:
org.quartz.dataSource.WL.jndiURL = OraDataSource
org.quartz.dataSource.WL.jndiAlwaysLookup = DB_JNDI_ALWAYS_LOOKUP
org.quartz.dataSource.WL.java.naming.factory.initial = weblogic.jndi.WLInitialContextFactory
org.quartz.dataSource.WL.java.naming.provider.url = t3://localhost:7001
org.quartz.dataSource.WL.java.naming.security.principal = weblogic
org.quartz.dataSource.WL.java.naming.security.credentials = weblogic
14. 改善持久性 JobStore 的性能
在使用 Quartz 的 JobStore 时,最大的关注面就是有关于与关系型数据库的交互。数据库 I/O(就像文件 I/O) 通常不是很快。你可以通过采取一些措施,如调优 SQL、增加索引和操作表和列等来改善性能。
15.创建新的JobStore
自己实现JobStore
15.1 实现JobStore接口
无论它们是否是用的数据库、文件系统、甚至是内存,所有的 JobStore 必须实现 JobStore 接口。你创建的新的 JobStore 也不例外。回头看本章前面部分,你会发现 RAMJobStore 直接实现了 JobStore 接口,JDBC JobStore 是 JobStroeSupport 的子类,它本身实现了 JobStore 接口。
JobStore 接口有 40 个方法,它要求任何 JobStroe 实现都必须实现这些方法,你的也一样。你如何实现那些方法完全依赖于你正构建的 JobStore 的类型。那不是说你的 JobStore 将只能有 40 个方法;这仅仅是接口需要的最小数量。这 40 个方法体现 JobStore 和 Scheduler 之间的公共契约。
下面讲几个接口方法:
①public void schedulerStarted() throws SchedulerException;
Scheduler 调用 JobStore 的 SchedulerStarted() 方法去通知 JobStore Scheduler 已经启动了。如果你看了 RAMJobStore 的实现,你能发现它在这个方法实现中什么也没做:
然而,假如你去看那两个 JobStore 的实现,你会看到在 Scheduler 在首次启动时进行了一些工作:
每一个 JobStore 实现会是唯一的,在接口方法内部实现的功能也是不同的。如果你是认真的去创建你自己的 JobStore,你就应当好好看看 RAMJobStore 的源代码来完全理解 JobStore 所有职责。RAMJobStore 应该作为你需要定制任何 JobStore 时的指南。