本文来自对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定义的命令注入攻击等。

Quartz最佳实践的更多相关文章

  1. 开源调度框架Quartz最佳实践

    开源调度框架Quartz最佳实践 Quartz是一个Java调度框架,当前的最新版本为2.2.1. 以Quartz 2.2.1版为例,Quartz最佳实践(用于生产系统)总结如下: 1.跳过更新检查Q ...

  2. spring-boot-2.0.3之quartz集成,最佳实践

    前言 开心一刻 快过年了,大街上,爷爷在给孙子示范摔炮怎么放,嘴里还不停念叨:要像这样,用劲甩才能响.示范了一个,两个,三个... 孙子终于忍不住了,抱着爷爷的腿哭起来:爷呀,你给我剩个吧! 新的一年 ...

  3. 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生

    [转].NET(C#):浅谈程序集清单资源和RESX资源   目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...

  4. ASP.NET跨平台最佳实践

    前言 八年的坚持敌不过领导的固执,最终还是不得不阔别已经成为我第二语言的C#,转战Java阵营.有过短暂的失落和迷茫,但技术转型真的没有想象中那么难.回头审视,其实单从语言本身来看,C#确实比Java ...

  5. 《AngularJS深度剖析与最佳实践》简介

    由于年末将至,前阵子一直忙于工作的事务,不得已暂停了微信订阅号的更新,我将会在后续的时间里尽快的继续为大家推送更多的博文.毕竟一个人的力量微薄,精力有限,希望大家能理解,仍然能一如既往的关注和支持sh ...

  6. ASP.NET MVC防范CSRF最佳实践

    XSS与CSRF 哈哈,有点标题党,但我保证这篇文章跟别的不太一样. 我认为,网站安全的基础有三块: 防范中间人攻击 防范XSS 防范CSRF 注意,我讲的是基础,如果更高级点的话可以考虑防范机器人刷 ...

  7. 快速web开发中的前后端框架选型最佳实践

    这个最佳实践是我目前人在做的一个站点,主要功能: oauth登录 发布文章(我称为"片段"),片段可以自定义一些和内容有关的指标,如“文中人物:12”.支持自定义排版.插图.建立相 ...

  8. Spring Batch在大型企业中的最佳实践

    在大型企业中,由于业务复杂.数据量大.数据格式不同.数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理.而有一些操作需要定期读取大批量的数据,然后进行一系列的后续处理.这样的过程就是" ...

  9. Atitit.log日志技术的最佳实践attilax总结

    Atitit.log日志技术的最佳实践attilax总结 1. 日志的意义与作用1 1.1. 日志系统是一种不可或缺的单元测试,跟踪调试工具1 2. 俩种实现[1]日志系统作为一种服务进程存在 [2] ...

随机推荐

  1. vue在组件中使用v-model

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. setTimeout定时器

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Android多渠道打包且根据不同产品打包不同的assets资源目录

    因为项目中存在多种环境,既要区分bebug与release版本,release又要区分测试环境与生产上线环境,每次打包都得浪费不少的等待时间:并且哪个版本有问题还得去切换环境一个个打包,关键是还得牢记 ...

  4. docker常用技巧

    1:运行中容器如何保存为一个镜像? docker commit 容器名字 镜像名字 2:怎么给容器增加名字 docker rename 容器id(或名字)name(新名字) 3:docker中的Doc ...

  5. Hive的安装搭建(三)

    03 Hive的安装搭建 Hive可以从源码中编译安装,也可以直接使用官网下载的安装包,在此处我们选择安装包解压安装的方式. Hive中最最重要的角色就是metastore 因此按照metastore ...

  6. 关于FileChannel的获取方式之open方法详解

    FileChannel.open(Path path, OpenOption... options); 例子使用JDK1.8 FileChannel open方法源码: public static F ...

  7. Codeforces 980 并查集/模拟贪心最小字典序 找规律/数去除完全平方因子 逆思维倍增预处理祖先标记点

    A /*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_bac ...

  8. 二、Ubuntu16.04安装搜狗wps

    1.搜狗: 安装搜狗输入法,下载地址:http://pinyin.sogou.com/linux/(搜索官网下载及安装方法),deb安装方法类似Windows的exe安装,安装后重启生效. 2.wps ...

  9. Spring MVC文件上传下载(转载)

    原文地址: http://www.cnblogs.com/WJ-163/p/6269409.html 上传参考 http://www.cnblogs.com/lonecloud/p/5990060.h ...

  10. 【LuoguP5289】[十二省联考2019] 皮配

    题目链接 题目描述 略 Sol 一道背包问题 首先暴力做法设 \(dp[i][j][k]\) 表示前 \(i\) 个城市的学校被分到第一阵营 \(j\) 人 第一门派 \(k\) 人的方案数. 中间一 ...