创业小团队,无论选择任何方案,都优先考虑节省成本。关于分布式定时调度框架,成熟的候选方案有XXL-JOB
、Easy Scheduler
、Light Task Scheduler
和Elastic Job
等等,其实这些之前都在生产环境使用过。但是想要搭建高可用的分布式调度平台,这些框架(无论是否去中心化)都需要额外的服务器资源去部署中心调度管理服务实例,甚至有时候还会依赖一些中间件如Zookeeper
。回想之前花过一段时间看Quartz
的源码去分析它的线程模型,想到了它可以基于MySQL
,通过一个不是很推荐的X
锁方案(SELECT FOR UPDATE
加锁)实现服务集群中单个触发器只有一个节点(加锁成功的那个节点)能够执行,这样子,就能够仅仅依赖于现有的MySQL
实例资源实现分布式调度任务管理。一般来说,有关系型数据保存需求的业务应用都会有自己的MySQL
实例,这样子就能几乎零成本引入一个分布式调度管理模块。某个加班的周六下午敲定了初步方案之后,花了几个小时把这个轮子造出来了,效果如下:
cron表达式是一个已经存在了很长时间的UNIX工具,因此它的调度功能非常强大且已经经过验证。CronTrigger类的功能是基于cron的调度功能实现的。
CronTrigger
使用"cron表达式",可以创建诸如“每周一至周五上午8:00”或“每月最后一个星期五上午1:30”的触发调度时间表(调度计划)。
cron表达式很强大,但是它使用起来也有可能相当混乱(这里大概的意思是说cron的用法相对复杂,容易出错)。本教程旨在解决创建cron表达式的一些谜题,为用户提供一个资源,让他们可以在论坛或邮件列表中提问之前访问这个教程(减少在论坛或者邮件中的提问)。
Quartz提供了一个用于插入附加功能的接口org.quartz.spi.SchedulerPlugin
。
Quartz集群目前与JDBC-Jobstore(JobStoreTX
或JobStoreCMT
)和(<–译者注:其实我觉得这里应该是"或")TerracottaJobStore
一起使用。功能包括负载均衡和Job故障转移(如果JobDetail
的“请求恢复(request recovery)”标志设置为true)。
Quartz的架构设计是模块化的,因此要运行它需要把几个组件组合在一起使用。幸运的是,有一些工具就是为了完成这个目标。
JobStore负责记录你提供到调度器的所有“工作数据”:所有的Job、所有的Trigger、所有的Calendar(org.quartz.Calendar)等等。为你的Quartz调度器选择一个合适的JobStore是一个重要的步骤。幸运的是,一旦你明白不同的JobStore之间的差异,那么作出合适的选择是十分简单的。
SchedulerListener和TriggerListener或JobListener十分相似,它接收调度器的相关事件,调度器的相关事件不一定和特定的Trigger或者Job相关。
监听器(listener)是你创建的对象,主要作用是接收和处理调度器回调的事件(event)。TriggerListener接收到与触发器(Trigger)相关的事件,JobListener接收与调度任务(Job)相关的事件。
CronTrigger通常比SimpleTrigger更有用,如果你需要一个基于类似日历的概念重复出现的工作调度计划,而不是SimpleTrigger的精确指定时间间隔。使用CronTrigger,你可以指定任务触发的时间表,例如“每周五中午”或“每个工作日和上午9:30”,甚至“每周一至周五上午9:00至10点之间每5分钟”和1月份的星期五”。即使如此,和SimpleTrigger一样,CronTrigger有一个startTime,它指定何时生效,以及一个(可选的)endTime,用于指定何时停止任务调度。
SimpleTrigger可以满足的调度需求是:在具体的时间点执行一次,或者在具体的时间点执行并且以指定的间隔重复执行若干次(其实永远重复也可以)。比如,你有一个Trigger,你可以设置它在2015年1月13日的上午11:23:54准时触发,或者在当前这个时间点触发,并且每隔2秒触发一次,一共重复5次。
1 / 2