Job 存储和持久化 (第一部分)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Shirley_John_Thomas/article/details/55260548

Quartz 用 JobStores 对 Job、Trigger、calendar 和 Schduler 数据提供一种存储机制。Scheduler 应用已配置的 JobStore 来存储和获取到部署信息,并决定正被触发执行的 Job 的职责。所有的关于哪个 Job 要执行和以什么时间表来执行他们的信息都来自于 JobStore。本章就来看 Quartz 中可用的各种类型的 JobStore,和如何使用他们,以及哪一个能适应你的需求。

"罗马非一日建成"

道格拉斯.亚当斯,《宇宙环游指南》

一. Job 存储
在前面章节中,我们未曾花过任何时间来讨论 Scheduler 的 Job 和 Trigger 是保存在哪儿的。我们也许已经实现了,然而,当你停止了 Scheduler 后,那些有关哪些 Job 已经运行和哪些 Job 没有运行的信息就会丢失掉。实际上,所有的关于正在运行中的 Job 的信息也被销毁。
当程序被重启后,Trigger 和 Job 的信息被加回去,且所有的一切又都正常了。我们假定,有一个 Job 是安排为 5 PM 执行,然而 Scheduler 在这个时间之前的五分钟(4:55 PM) 时停掉了。如果你在 5:05 PM 时重新启动了 Scheduler 的话将会发生什么事情呢?Scheduler 还会记得要在 5 PM 触发这个 Job 的吗?答案就是看它是依赖于你使用的哪种类型的 JobStore,以及是如何对它配置的。
二. Quartz 中的 Job 存储
Quartz 支持对 Scheduler 信息的几种不同类型的存储机制。在 Quartz 中两种可用的 Job 存储类型是:
    · 内存(非持久化) 存储
    · 持久化存储
默认时,我们在前面几章的例子中已经使用了内存存储机制。两种类型都是用来服务于相同的目的:存储 Job 信息。然而他们各自是如何运作的,而且他们提供给 Scheduler 的功能是很不一样的。
·JobStore 接口
Quartz 为所有类型的 Job 存储提供了一个接口。这个接口位于 org.quartz.spi 包中,叫做 JobStore。所有的 Job 存储机制,不管是在哪里或是如何存储他们的信息的,都必须实现这个接口。
JobStore 可以列出太多的方法来,但是 JobStore 接口的 API  可归纳为下面几类:
    ·Job 相关的 API
    ·Trigger 相关的 API
    ·Calendar 相关的 API
    ·Scheduler 相关的 API
Quartz 的使用者几乎从不访问或是查看实现了 JobStore 接口的具体类;他们被 Quartz Scheduler 在运行期间内部使用来获取 Job 和 Trigger 信息。不过很值得练习一下,使你自己能熟悉每一种类型,这样你就能更好的理解这些为你所提供的存储机制,并有助于你在 Quartz 应用中选择一个正确的类型。
三. 使用内存来存储 Scheduler 信息
Quartz 直接可用的配置就是把 Job 和 Trigger 信息存储在内存中的。这个解释了为什么,对于前面章节中的例子,每次我们重启了 Quartz 应用程序后,Scheduler 的状态,包括 Job 和 Trigger 信息都丢失了。每回 Java 虚拟机(JVM) 关闭之后,它所占用的内存就释放回给了操作系统,因此任何关于 Job 和 Trigger 的信息都随 JVM 而丢失。
Quartz 的内存 Job 存储的能力是由一个叫做 org.quartz.simple.RAMJobStore 类提供了,当如我们所说,它实现了 JobStore 接口的。RAMJobStore 是 Quartz 的开箱即用的解决方案。对此,我们的意思是说,除非你改变了配置,否则在任何 Quartz 应用中都将使用 RAMJobStore。相比于其他的,使用这种 JobStore 可带来几个好处。
首先,RAMJobStore 是配置最简单的 JobStore:已给你配置好了的。当你下载并安装 Quartz 后,就已为你配置了使用 RAMJobStore 作为存储机制。你能在默认的 quartz.properties 文件中看到这个,如代码 6.1 所示。
代码 6.1. 没有其他配置时默认的 quartz.properties 文件

  1. # Default Properties file for use by StdSchedulerFactory
  2. # to create a Quartz Scheduler Instance, if a different
  3. # properties file is not explicitly specified.
  4. org.quartz.scheduler.instanceName = DefaultQuartzScheduler  
  5. org.quartz.scheduler.rmi.export = false
  6. org.quartz.scheduler.rmi.proxy = false
  7. org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
  8. org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool  
  9. org.quartz.threadPool.threadCount = 10  
  10. org.quartz.threadPool.threadPriority = 5  
  11. org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
  12. org.quartz.jobStore.misfireThreshold = 60000  
  13. org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore 

# Default Properties file for use by StdSchedulerFactory # to create a Quartz Scheduler Instance, if a different # properties file is not explicitly specified. org.quartz.scheduler.instanceName = DefaultQuartzScheduler org.quartz.scheduler.rmi.export = false org.quartz.scheduler.rmi.proxy = false org.quartz.scheduler.wrapJobExecutionInUserTransaction = false 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.jobStore.misfireThreshold = 60000 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
代码 6.1 中显示了包含在 Quartz 二进制包中的默认的 quartz.properties 文件。当你没在你自己的程序中引入一个 quartz.properties 文件,这个属性文件就会得到使用。你可以从默认的 quartz.properties 文件的最后一行看到,RAMJobStore 是名为 org.quartz.jobStore.class 的配置属性的默认值。甚至是未在 quartz.propterties 中设置 org.quartz.jobStore.class 属性时,RAMJobStore 也是默认所用的 JobStore。这是硬编码到 Scheduler 工厂初始化程序中的。
另一使用 RAMJobStore 是优点是它的速度。因为所有的 Scheduler 信息都保存在计算机内存中,访问这些数据随着电脑而变快。这儿不存在进程外的调用,没有数据库连,仅仅是原始而简单的内存访问。再也找不到比这更快的方式了。
·RAMJobStore 的 Job 易失性

你也许还记得在第四章,"部署 Job" 中讲过,Job 可以配置一个易失性属性。当这个易失性属性设置为 false,Job 将会在应用关闭之间持久化下来。这个属性对于用 RAMJobStore 时是不起作用的;那一行为是显式的为持久性的 JobStore 所保留的。
·配置 RAMJobStore
配置你的 Quartz 应用来使用 RAMJobStore 是非常简单的。假如你正用一个定制的 quartz.properties 文件,而不是来自于 Quartz JAR 文件中的,那么加上这行到你的属性文件中即可:
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
这就你要用 RAMJobStore 所要做的事情,正如我们所说的,没有比这更简单的了。
·加载 Job 到 RAMJobStore 中

既然 RAMJobStore 的目的是存储 Scheduler 信息,那么那些信息一开始是如何被加载到内存中的呢?你可以用两种方式加载 Job 信息。首先,你能硬编码你的 Job、Trigger、calendar 和 listener 到你的代码中。如第三章,"Hello,Quarz",第四章,"部署 Job" 所指出的,然而,这总是一件很危险的事情,因为这对于维护来说将是个梦魇。任何的改变,即使是微不足道的,都要修改代码然后重新编译。甚至是只改变触发的时间,也要改代码然后重编译。这没什么大不了的,你说呢?那也许对于小小的程序是这样的,但对于有大量的 Job 和 Trigger 的程序却成了一个大问题。
第二种途径是使用 JobInitializationPlugin,这会在第八章,"使用 Quartz 插件" 中详细讨论。这个 Quartz 插件使用一个 XML 文件来加载 Job、Trigger、Calendar 和其他你需要加载的东西。这种方式的优点是,当有改变时只需要对这个 XML 文件作改动,不用改代码,不用重编译,仅用一个文本编辑器。阅读第八章可获得关于 Quartz 插件更多的信息。
·RAMJobStore 的缺点
你要问了,"RAMJobStore 不能全是正面的,对吗?"。没错,确实如此。我们前面提到几个使用 RAMJobStore 的优点。现在,让我们来谈谈它的一个负面的地方:因为计算机的内存是易失性的,当你的 Quartz 程序被停止了,它会把内存释放回操作系统,当然了,伴随着存储在所释放内存里的别的内容就是这些部署信息了。
假如你的程序的 Scheduler 信息需要在程序重启之间能保持着,那么你需要看看持久性的 JobStore 了。

猜你喜欢

转载自blog.csdn.net/Shirley_John_Thomas/article/details/55260548