第10课 配置、资源利用率和SchedulerFactory
Quartz的架构是模块化的,因此要让它运行起来,需要将多个组件整合到一起。幸运地是,已经有一些工具帮助我们实现这个。
在Quartz可以工作之前,需要配置的主要组件有:
- ThreadPool
- JobStore
- DataSource(如果需要的话)
- Scheduler自己
ThreadPool为Quartz提供了一组线程用于执行Job。线程池中的线程越多,那么同时执行的Job数量就越大。然而,太多的线程会让系统停顿。大多数的Quartz用户发现大约5个线程就足够了:因为在任何时间,它们不会超过100个job,而且这些job通常也不是同时调度的,job是个短命鬼(完成的非常快)。其它一些用户发现它们需要10、15、50甚至100个线程-因为它们有成千上万个trigger在不同的调度表中,这导致在同一时刻可能有平均10到100个job需要执行。找到scheduler线程池的合适大小依赖于你用scheduler干什么。因此没有真正的规则,除了尽量能保持线程池越小越好(考虑你的机器的资源),但是确保你有足够的线程触发你的Job。注意,如果trigger的触发时间到了,但是没有可用的线程,那么Quartz会阻塞(或暂停),直到有可用的线程出现,然后Job就会执行-比正常时间可能晚几毫秒。如果超过了scheduler配置的失败门限时间,这也可能导致线程失败。
ThreadPool接口定义在org.quartz.spi包下,你可以任何方式创建ThreadPool的实现。Quartz自带了一个简单的(但是已经满足了)线程池,名为org.quartz.simpl.SimpleThreadPool。这个线程池简单的维护一个固定大小的线程,不会增长,也不会减少。但是它相当稳定,测试的非常好,几乎所有用户都用这个线程池。
本教程的第9课讨论了JobStore和DataSource。值得注意的是,所有的 JobStore都实现了org.quartz.spi.JobStore接口,如果打包的JobStore不满足你的需要,你可以自己创建一个。
最后,你需要创建Scheduler实例。Scheduler自己需要起一个名字,需要告知它的RMI设置,持有JobStore和ThreadPool的引用。RMI设置包括Scheduler是否应该自己创建RMI服务器(让它自己变得对远端可用),使用的主机和端口等等。StdSchedulerFactory也可以产生Scheduler实例,这些实例实际上是远端进程创建的Scheduler代理(RMI stubs)。
StdSchedulerFactory
StdSchedulerFactory是org.quartz.SchedulerFactory接口的实现。它使用一组属性(java.util.Properties)来创建和实例化 Quartz Scheduler。这些属性通常是存储到文件,或者从文件加载,但是也可以由你的程序创建或者直接手动传递给这个工厂。简单的调用工厂的getScheduler()方法就会生成一个scheduler,初始化它(ThreadPool、JobStore和 DataSource),并返回一个应用给它的公共接口。
在Quartz发布包的doc/config目录下有一些示例配置(包括属性的描述)。你可以在Quartz文档的Reference章节下的Configuration手册中找到完整的文档。
DirectSchedulerFactory
DirectSchedulerFactory是另一个 SchedulerFactory实现。它对于那些希望以编程方式创建Scheduler的用户来说是很有用的。通常不鼓励使用它,原因如下:(1) 它需要用户完全理解它们在做什么;(2)它不允许声明式配置,话句话说,你必须硬编码所有的scheduler配置。
日志
Quartz使用SLF4J框架记录日志。为了调整日志设置(如输出的大小及位置s),你需要理解SLF4J框架,这已经超出了本文档的范围。
如果你想要捕获trigger触发和job执行的信息,你需要使用org.quartz.plugins.history.LoggingJobHistoryPlugin和org.quartz.plugins.history.LoggingTriggerHistoryPlugin.