Quartz最佳实践

本文来自对http://www.quartz-scheduler.org/documentation/best-practices.html的翻译。

表示还没用过Quartz,正准备用的,然后在官网上看到了这个,然后觉得还挺短的,就翻译一下。

最佳实践

对生产环境中使用Tips

任务数据映射Tips

触发Tips

JDBC的JobStore

daylight savings time(这个翻译是夏令时,所以我不知道怎么翻译了)

任务

监听器(触发监听器,任务监听器,调度监听器)

通过应用暴露调度器功能

生产环境中的建议

跳过更新检查

Quartz在连接服务的时候包含了一个“更新检查”的特性,这个特性会检查是否有Quartz的新版本可用。

这个个检查是异步进行的,并不会影响Quartz的启动和初始化时间,如果连接失败的话,它会优雅地结束。

如果运行了检查,而且找到了新的版本,将会在Quartz的日志中进行记录。

你可以将Quartz配置属性设置org.quartz.scheduler.skipUpdateCheck: true或者将系统属性org.terracotta.quartz.skipUpdateCheck=true(这个是在系统环境或者在java命令行中以-D加入),这样就可以禁用掉Quartz的更新检查。建议你在生产环境的部署中禁用更新检查。

任务数据映射的建议

在JobDataMap中仅仅存储原始数据类型(包括Strings)

在JobDataMap中仅仅存储原始数据类型(包括Strings)可以避免短期或长期的序列化的问题。

使用合并的JobDataMap

在任务执行的时候,JobExecutionContext中的JobDataMap作为一个convenience。它是通过在JobDetail中的JobDataMap和Trigger中的JobDataMap合并而来,后者中的值会覆盖前面一个中同名变量的值。

当你有一个任务在scheduler中,而且这个任务又会被多个Triggers重复使用,那么你最好把值存在Trigger的JobDataMap中,这样对于每次独立的任务触发时,你就可以为Job提供不同的数据输入啦。

根据以上所述,我们提出了如下的最佳实践:在调用Job.execute(...)方法时,一般来说应该从JobExecutionContext中的JobDataMap中解析变量的值,而不是直接从JobDetail的JobDataMap中解析。

触发器建议

使用TriggerUtils

TriggerUtils:

提供了一个简单的方法来创建triggers(schedules)

有很多不同的方法通过schedules来创建triggers以满足特定的描述,这个要比直接实例化特定类型的triggers(SimpleTrigger,CronTrigger等)然后调用不同的setter方法来配置它们方便许多

提供了一个简单的方法来创建日期(比如start/end日期)

提供了分析triggers的助手(比如计算剩余的触发时间)

JDBC JobStore

永远都不要直接往Quartz的表中写数据

通过SQL直接往数据库中写入scheduling数据而不是通过API会造成一下问题:

会造成数据腐化(被删除的数据,混乱的数据)

会造成任务在到达执行点的时候像没有执行就消失了

会造成当触发时间到来时,而任务还未执行

可能会造成死锁

其他奇怪的问题和数据腐化

永远不要在同一个数据库中将一个非集群的调度器指向另一个相同名字的调度器

如果你在同一套数据库表中指定了多于一个的调度器实例,并且这些实例并不是配置在集群中,那么下面的情况将有可能会发生:

会造成数据腐化(被删除的数据,混乱的数据)

会造成任务在到达执行点的时候像没有执行就消失了

会造成当触发时间到来时,而任务还未执行

可能会造成死锁

其他奇怪的问题和数据腐化

确保足够的数据源中的连接数量

建议将你的数据源连接数配置为配置为线程池中工作线程数加3。如果你的应用还要经常调用scheduler的API,那么你还需要增加额外的连接数量。如果你正在使用JobStoreCMT,那么“未管理的”数据源的最大连接数至少为4。

夏令时

避免将任务安排在接近夏令时的转移时间

注意:本地的时钟向前或者向后转移时和总的时间的细节可以在如下链接中找到:

https://secure.wikimedia.org/wikipedia/en/wiki/Daylight_saving_time_around_the_world.

SimpleTriggers不受夏令时的影响,这是因为它们总是在毫秒时刻被精确地触发,并且在进过了精确的毫秒数之后会再次被触发。

由于CronTriggers会在给定的时/分/秒被触发,当夏令时转移时到来的时候,它们会受到这些怪事的影响。

举一个可能发生的例子,在夏令时的美国时区/位置进行调度的时候,如果使用CronTrigger并且调度的触发时间是在1:00 AM和2:00 AM之间时会发生下列的问题:

1:05 AM也许会发生两次!可能会重复地触发CronTrigger

2:05 AM也许永远不会发生!可能会遗漏CronTrigger的触发

同时,时间和调整量要根据当地位置来调节。

其他的触发器类型是根据日历的移动而不是根据确切的时间量来进行的,例如CalenderIntervalTrigger,将会同样地受影响,但不是错过触发或者触发两次,而是将它的触发时间偏移一个小时。

Jobs

等待条件来到

长时间运行的任务会阻止其他任务的运行(如果在线程池中所有的线程都繁忙)。

如果你认为需要调用Thread.sleep()这个方法来停止工作线程执行任务,这是一个典型的信号,任务不会完成其余的任务,因它必须等待某些条件的到来(比如某些数据可读)。

一个更好的方法是释放线程(退出任务)并且允许其他任务在这个线程执行。任务可以重新调度自己,或者在它退出之前其他任务。

抛出异常

一个任务的执行方法应该包含在try-catch块中,以此处理可能发生的异常。

如果一个任务抛出一个异常,Quartz一般会马上再执行它(可能会抛出相同的异常)。最好是任务捕获所有它可能遇到的异常并处理它们,然后重新调度自己或其他的任务。

可恢复性和幂等性

带有"recoverable"的任务会在调度器失败时重新执行。这意味着某些任务的工作将会被执行两次。

这意味着在编写任务的时候它的工作应该是幂等的。

监听器(TriggerListener,JobListener,SchedulerListener)

保持编写简洁高效的监听器

不建议在监听器中完成大量的工作,因为将要执行任务的线程(或者完成触发和引发另一个任务等)将会绑定在监听器上。

处理异常

每个监听器的方法都应该在try-catch块中处理所有可能的异常。

如果一个监听器抛出了一个异常,可能会造成其他的监听器无法被通知到或阻止其他任务的执行等。

通过应用来暴露调度器的功能

小心安全问题!

有的用户通过应用程序接口来暴露Quartz的调度功能。这会非常有用,虽它可能会造成极度的危险。

确保你没有错误地允许用户定义他们想要的任何参数和任何类型的任务。例如,Quartz会带有一个预定的任务org.quartz.jobs.NativeJob,这个任务将会在它们定义的任意的本地系统上执行命令。恶意的用户可能会使用这个来控制或者摧毁你的系统。

同样的像SendEmailJob之类的任务,并且事实上任何其他的任务都可以被当作恶意用途。

如果允许用户定义任意他们想要的任务将会是你的系统遭受各种可能的危害,等同于OWASP和MITRE定义的命令注入攻击等。

时间: 2024-10-07 23:16:22

Quartz最佳实践的相关文章

开源调度框架Quartz最佳实践

开源调度框架Quartz最佳实践 Quartz是一个Java调度框架,当前的最新版本为2.2.1. 以Quartz 2.2.1版为例,Quartz最佳实践(用于生产系统)总结如下: 1.跳过更新检查Quartz内置了一个“更新检查”特性,因此Quartz项目每次启动后都会检查官网,Quartz是否存在新版本.这个检查是异步的,不影响Quartz项目本身的启动和初始化.可以在Quartz配置文件中,设置org.quartz.scheduler.skipUpdateCheck的属性为true来跳过更

基础入门_Python-模块和包.运维开发中watchdog事件监视的最佳实践?

简单介绍: 说明:  此模块是一个跨平台的PY库和SHELL工具,可以监视文件系统事件(增加/删除/修改) 快速安装: pip install --upgrade watchdog 日志记录: event_handler = LoggingEventHandler() -> event_handler 说明: 创建一个日志处理句柄,其实LoggingEventHandler是继承自FileSystemEventHandler类,只是重写了增删查改的回调函数,直接调用logging模块写到对应lo

基础入门_Python-内建函数.运维开发中eval内建函数的最佳实践?

简单介绍: 说明: 在指定命名空间中计算参数字符串的有效表达式,并返回一个对象, Help on built-in function eval in module __builtin__: eval(...)     eval(source[, globals[, locals]]) -> value          Evaluate the source in the context of globals and locals.     The source may be a string 

45个实用的JavaScript技巧、窍门和最佳实践

如你所知,JavaScript是世界上第一的编程语言,它是Web的语言,是移动混合应用(mobile hybrid apps)的语言(比如PhoneGap或者Appcelerator),是服务器端的语言(比如NodeJS或者Wakanda),并且拥有很多其他的实现.同时它也是很多新手的启蒙语言,因为它不但可以在浏览器上显示一个简单的alert信息,而且还可以用来控制一个机器人(使用nodebot,或者nodruino).掌握JavaScript并且能够写出组织规范并性能高效的代码的开发人员,已经

毫秒必争,前端网页性能最佳实践

你愿意为打开一个网页等待多长时间?我一秒也不愿意等.但是事实上大多数网站在响应速度方面都让人失望.现在越来越多的人开始建立自己的网站,博客,你的网页响应速度如何呢?在这篇文章中我们来介绍一下提高网页性能的最佳实践,以及相应的问题解决方案,让站长或者即将要成为站长的朋友了解如何去测试和提高网站响应速度,对自己的网站更有信心. 最佳实践 最佳实践我们引用的来自yahoo前端性能团队总结的35条黄金定律.原文猛击这里.下面我们分门别类将每条的关键点总结一下. 网页内容 减少http请求次数 减少DNS

atitit.手动配置列表文件的选择and 数据的层次结构 attilax总结最佳实践--yaml

atitit.手动配置列表文件的选择and 数据的层次结构 attilax总结最佳实践--yaml 1. yaml是个好的选择.. 1 2. 数据的层次结构--结构:hash,list,和block literal. 1 3. yaml跟json的实现区别 1 4. xml的优点及json的问题 2 4.1. ide友好 2 4.2. JSON也适合与任何数据,复杂struts难以阅读 2 4.3. json难以手工维护 3 5. 基于YAML的开源项目解析YAML文件最常用的Java库是JvY

京东前端:PhantomJS 和NodeJS在网站前端监控平台的最佳实践

1. 为什么需要一个前端监控系统 通常在一个大型的 Web 项目中有很多监控系统,比如后端的服务 API 监控,接口存活.调用.延迟等监控,这些一般都用来监控后台接口数据层面的信息.而且对于大型网站系统来说,从后端服务到前台展示会有很多层:内网 VIP.CDN 等. 但是这些监控并不能准确地反应用户看到的前端页面状态,比如:页面第三方系统数据调用失败,模块加载异常,数据不正确,空白开天窗等. 相关厂商内容 Native动态化最新技术解析 不可错过的智能时代的大前端 性能优化最佳实践经验谈 百度技

[转] React 最佳实践——那些 React 没告诉你但很重要的事

前言:对很多 react 新手来说,网上能找到的资源大都是些简单的 tutorial ,它们能教会你如何使用 react ,但并不会告诉你怎么在实际项目中优雅的组织和编写 react 代码.用谷歌搜中文“ React 最佳实践”发现前两页几乎全都是同一篇国外文章的译文...所以我总结了下自己过去那个项目使用 React 踩过的一些坑,也整理了一些别人的观点,希望对部分 react 使用者有帮助. React 与 AJAX React只负责处理View这一层,它本身不涉及网络请求/AJAX,所以这

SQL Server集成服务最佳实践:语句优化

SQL Server集成服务(SQL Server Integration Services,SSIS)在其前辈DTS(Data Transformation Services,数据转换服务)的根基上进步了不少,从可用性.性能和并行等方面来说,它已经成长为一个企业级ETL(Extraction, Transformation and Loading,抽取.转换和加载)产品,除了是一个ETL产品外,它也供给了各种内置任务来管理SQL Server实例.虽然SSIS的内部架构已经被设计为供给极好的性