开源调度框架Quartz最佳实践
作者:chszs,转载需注明。博客主页:
Quartz是一个Java调度框架,当前的最新版本号为2.2.1。
以Quartz 2.2.1版为例,Quartz最佳实践(用于生产系统)总结例如以下: 1、跳过更新检查 Quartz内置了一个“更新检查”特性,因此Quartz项目每次启动后都会检查官网。Quartz是否存在新版本号。这个检查是异步的。不影响Quartz项目本身的启动和初始化。 能够在Quartz配置文件里。设置org.quartz.scheduler.skipUpdateCheck的属性为true来跳过更新检查。 2、JobDataMap技巧在JobDataMap应该只存储原始的数据类型(包括字符串),这样能够避免数据序列化的问题以及长期运行的问题。3、使用合并后的JobDataMap官方推荐。Job.execute()方法通常应该从JobExecutionContext发现的JobDataMap中取回数据。而不是直接从JobDetail中取数据。 4、使用TriggerUtilsTriggerUtils工具类作用例如以下:1)提供了一种更简单的创建触发器的方式。2)提供了带调度器创建触发器的各种方法来满足特殊需求,与直接初始化特殊类型的触发器(SimpleTrigger、CronTrigger),然后调用各种setter方法进行配置相反。3)提供了更为简单的创建日期时间的方法。4)提供了辅助类来分析触发器(比方计算未来的激活次数等)。5、一定不要直接写数据到Quartz表通过SQL语句写调度数据到数据库表,而不应该使用调度API来写数据,由于:1)会导致数据冲突(删除数据、争夺的数据)。2)会导致当触发器的激活时间到了时,Job会看起来不见了。3)会导致当触发器的激活时间到了时。Job会不运行。看起来“只坐在那儿”。 4)可能会导致死锁5)还可能导致其它奇怪的问题和数据崩溃等6、一定不要把多个非集群的调度器实例指向同一个数据库表假设把多个调度器实例指向同一个数据库表。并且这些调度器实例没有做集群配置,那么可能会发生:1)会导致数据冲突(删除数据、争夺的数据)。 2)会导致当触发器的激活时间到了时。Job会看起来不见了。3)会导致当触发器的激活时间到了时。Job会不运行,看起来“只坐在那儿”。4)可能会导致死锁5)还可能导致其它奇怪的问题和数据崩溃等7、确保适合的数据源连接数官方推荐数据源的最大连接数应该配置为线程池的最小工作线程数的3倍。假设你还须要额外的连接(比方频繁地调用调度器API),假设还使用了JobStoreCMT,那么非托管的数据源的最大连接数应该是至少4倍以上。8、避免调度Job的时间安排在夏令时转换的交界处SimpleTrigger触发器不受此影响。9、等待条件假设连接池全部的线程都处于繁忙状态。那么长期运行的Job会阻止其它Job的运行。假设在工作线程运行Job时调用Thread.sleep()后,Job余下的工作有可能得不到运行,由于会等待一些条件(比方数据记录有效后)为真后再运行。最佳的解决方式是释放工作线程(退出Job)。同意其它Job在线程上得到运行。Job能够又一次调度自身,或者等其它Job在退出前调度它。 10、Job抛出异常Job运行方法应该包括try-catch代码块,以处理各种可能发生的异常。 假设Job抛出异常。Quartz一般会马上又一次运行(看起来会再次抛出相同的异常)。最佳的方式是让Job能够捕获它可能会遇到的全部异常,处理这些异常,然后再重调度Job。
11、可恢复性和幂等性标记为“可恢复的”、在进行中的Job在调度器失效后是能够自己主动又一次运行的。这意味着相同的Job工作可能会运行两次。12、在监听器中保持代码简洁高效不鼓舞监听器内运行大量的工作,运行Job或完毕触发器并激活还有一个Job等,都应该绑定到监听器。 13、监听器抛出异常每一个监听器(TriggerListener、JobListener和SchedulerListener)应该包括try-catch代码块。以处理各种可能发生的异常。假设监听器抛出异常。它也许会导致其它监听器得不到通知或阻止Job的运行等等。 14、注意安全一些开发人员会通过应用程序的用户接口暴露Quartz调度器的功能,这非常实用,但也非常危急。由于恶意用户能够通过这样的方式控制或破坏您的系统。