本文主要是介绍与Quartz的半日情结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
12月8日与Quartz的半日情结
最近一直在处理报表订阅的一些历史遗留问题,编码人离职了,理所当然就得是我这个专门负责给人"擦PP"的人去解决了.虽然解决了大部分问题,但今天好悬就把偶搞傻掉了.
先说下Quartz这个玩意吧,说得挺悬乎,是一个开源组织在任务调度方面的一个框架.它可以用来创建简单的任务,当然也可以去运行上万个任务的复杂程序表.
之前解决问题时,没怎么涉及到这个东西,即便是涉及,那也是非常简单的配置参数错误或者分组混乱而已,所以对它也没有什么了解或是学习.但今天出现的问题,真是把我逼到了悬崖上,呵呵.
怎么说呢,问题那是相当严重啊.B/S下的Quartz应用配置涉及到三个文件:
1.配置启动Quartz服务的web.xml;
2.配置Quartz运行时环境的quartz.properties;
3.配置任务明细的任务单--job.xml.
PS:后两个配置文件的名称可变.
我们的问题首先出在,应用服务器启动状态下,当对任务进行了修改时(即修改了job.xml中的任务明细),Quartz无法响应这种变化.也就是说,Quartz并没有进行"有状态"作业!这对于我来说的确是一个比较棘手的问题,因为针对我们的报表订阅来说,无论是修改了任务明细中的参数列表--JobDataMap,或是CronExpression中的定时表达式,都应该立即做出响应,并按照新的配置参数去执行这个任务并发送Excel或PDF格式的报表.
怎么说呢,这个问题并不至于让我慌乱,因为直觉告诉我,使用Quartz的应用job reload应该是一个相对来说比较常见的事情,而一个在任务调度领域倍受好评的开源框架不会不去解决它.Google了一下,不知是我的搜索条件写得准确还是这个问题较常见,第一条结果就是我想要的.只需要在quartz.properties中加入下面两行配置即可:
#自动扫描任务单并发现改动的时间间隔,单位为秒
org.quartz.plugin.jobInitializer.scanInterval = 10
#覆盖任务调度器中同名的jobDetail,避免只修改了CronExpression所造成的不能重新生效情况
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
搞定这个问题后本来应该是大吉安事了,没想到的是,前边这个问题仅仅是暴风雨的前夜而已...
测试任务单变更自检的问题时,突然发现,当通过web页面提供的任务配置接口进行报表订阅任务的新增、修改等操作时,由于job.xml是在classes目录下,所以tomcat会进行自动的reload.这看起来好象没什么问题,但在实际的应用环境下却非常危险,因为web.xml中配置的随tomcat启动而启动的程序都会reload.可能这些程序很简单,并不会产生什么问题,但我们的软件则不同,随tomcat的启动,会有很多服务被启动并进行着极为复杂的操作,所以classes目录下的程序配置项都不会轻易修改.即使是修改,那也会重新启动tomcat使服务正常运转.
修改了任务单后观察了下,果然最郁闷的事情发生了,某个服务出现了Illegal Access问题.这还只是一个服务,谁又能保证其它的服务不会产生问题呢?最终的结论很让我沮丧:一是使用Quartz去做这个极容易改变任务明细的产品,彻头彻尾就是错误的,从而直接否定了目前报表订阅的所有工作,包括前期的分析与设计;二就是答应用户12月可以使用的报表订阅产品搁浅,因为这样就投入使用,就好象浑身缠满TNT去玩Zippo一样,后果...
在思考如何解决这个问题的过程中,我以Debug的方式,将Quartz的源代码从头到尾的跑了N遍.不仅弄清楚了其工作原理,而且还知道了它的配置项对任务执行所起到的作用.感觉Quartz嘛,就是一个帮我们考虑了很多可能发生的事情,并且还给了我们一些额外功能的Timer.
问题的解决往往就在不经意之间,并且要敢于向常理说不.既然Quartz的两个主要配置文件名称可变,而且是从web.xml加载quartz.properties,又从quartz.properties找到job.xml,那么凭什么job.xml就必须要放到classes目录下呢?
好,既然不凭什么,那就彻底颠覆一下吧,呵呵.首先将job.xml拿到web目录下,就放到config/job.xml吧.然后修改quartz.properties文件,将文件指向修改成绝对路径:
org.quartz.plugin.jobInitializer.fileName = D:/tomcat/webapps/report/config/job.xml
然后修改job.xml的XML文件操作接口,将配置文件获取部分的代码从/WEB-INF/classes目录变更到/config目录.测试通过!这种不按常理出牌的方式,解决了所有问题,仍然可对任务明细进行操作,并且通过quartz.properties中的配置让Quartz自己发现这种变更.而且,job.xml无论如何变更,tomcat都不会reload,因为它已经不在classes目录下了.捏哈哈^_^
在Debug过程中,发现Quartz的一个小问题,可能会对资源造成无谓的占用.那就是当一个任务从job.xml中被删除时,Quartz是不会响应这种减少任务的改变的,此任务的进程仍然被占用,而且任务还会被执行.处理这种问题,可以考虑在JobDataMap中增加是否执行的配置项,即使任务会执行,但根据这种配置项,仍然可以拒绝下一步的操作.当然了,修改CronExpression使之成为一个永远不会执行到的时间也是一个BT的办法.
最后再来一个个人想法,算是以后考虑实现的Quartz高级应用吧.那就是目前Quartz只会去加载一个job.xml.这对于多模块使用job.xml有一点不爽,因为无法具体将任务按照不同模块进行区分或单独维护.实现SchedulerPlugin接口并提供多任务文件加载功能,将会是解决这个事情的好方法.
从入门到精通,半天时间不是啥难事,上次是Ajax,这次是Quartz而已.
这篇关于与Quartz的半日情结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!