Springboot下quartz定时器遇到重复执行的问题

  
  最近在玩springboot,这个东西玩起来很欢乐。在集成quartz框架的时候,遇到了一些问题,百度了挺久,有些有参考价值,其他的并没有什么用,搞了挺久,从现象上算是解决了,但是实际情况还需要验证,先把总解的东西记一下,免得忘记了,有问题以后再来修改。

问题

  首先得说明,这个问题并不是指 每一次执行job都执行2次,而是指,在项目起了之后,首次执行一个job的时候 会多次执行(我这边的现象是执行2次,同时执行2次,一瞬间2个线程去执行)
  网上看下来大部分的问题是没一次job都执行了2次,貌似是因为spring 和 tomcat 多次读取配置,所以导致执行2次,具体的百度,我没遇到问题不瞎bb。
  还有一种方法貌似是 在quartz.properties 配置文件里面加上这个锁,具体也是百度

1
org.quartz.jobStore.acquireTriggersWithinLock=true

目前解决方法

   在配置 SchedulerFactoryBean 的时候 有一个配置是延时启动,这个配置的目的是 避免系统未完全启动却开始执行定时任务的情况 ,然而可能就是这个配置导致了问题的产生

1
2
SchedulerFactoryBean bean = new SchedulerFactoryBean();
bean.setStartupDelay(15);

   众所周知,job的执行时间控制是 tigger控制的,因为是测试这个功能,所以我配置的时间间隔为10秒执行一次

1
tigger.setCronExpression("0/10 * * * * ?");

   但是这样跑起来就会出问题,就像下面这样,可以看到几乎是同一个时间 有1和2两个线程去执行testjob1,这样就很操蛋了

1
2
3
4
5
6
7
8
9
11:54:52  [Quartz Scheduler [schedulerFactory]] INFO  org.quartz.core.QuartzScheduler - Scheduler schedulerFactory_$_WhiteMagic2014.local1534391675702 started.
11:54:52 [schedulerFactory_QuartzSchedulerThread] INFO com.scfire.springboot.quartzJob.TestJob1 - 构造方法1
11:54:52 [schedulerFactory_Worker-1] INFO com.scfire.springboot.quartzJob.TestJob1 - test job 1
11:54:52 [schedulerFactory_Worker-1] INFO com.scfire.springboot.quartzJob.TestJob1 - Job fired at Thu Aug 16 11:54:52 CST 2018
11:54:52 [schedulerFactory_Worker-1] INFO com.scfire.springboot.quartzJob.TestJob1 - Job nexe fire time: Thu Aug 16 11:54:50 CST 2018
11:54:52 [schedulerFactory_QuartzSchedulerThread] INFO com.scfire.springboot.quartzJob.TestJob1 - 构造方法1
11:54:52 [schedulerFactory_Worker-2] INFO com.scfire.springboot.quartzJob.TestJob1 - test job 1
11:54:52 [schedulerFactory_Worker-2] INFO com.scfire.springboot.quartzJob.TestJob1 - Job fired at Thu Aug 16 11:54:52 CST 2018
11:54:52 [schedulerFactory_Worker-2] INFO com.scfire.springboot.quartzJob.TestJob1 - Job nexe fire time: Thu Aug 16 11:55:00 CST 2018

   折腾了很久才考虑到这2个时间的配置可能是引起问题的原因,因为在启动之后,job的执行间隔是10秒,而延时启动时间确是15秒,这就导致了在延时的期间有一个任务没有执行到,可能就是这个原因导致了在首次执行job的时候补上了上一次miss的job,这个是我的猜测,跟着这个猜测我把tigger的执行时间调成了 0/20 ,再起服务,确实,并没有同时执行多次

1
2
3
4
5
6
7
8
9
11:55:49  [Quartz Scheduler [schedulerFactory]] INFO  org.quartz.core.QuartzScheduler - Scheduler schedulerFactory_$_WhiteMagic2014.local1534391733865 started.
11:55:50 [schedulerFactory_QuartzSchedulerThread] INFO com.scfire.springboot.quartzJob.TestJob1 - 构造方法1
11:55:50 [schedulerFactory_Worker-1] INFO com.scfire.springboot.quartzJob.TestJob1 - test job 1
11:55:50 [schedulerFactory_Worker-1] INFO com.scfire.springboot.quartzJob.TestJob1 - Job fired at Thu Aug 16 11:55:50 CST 2018
11:55:50 [schedulerFactory_Worker-1] INFO com.scfire.springboot.quartzJob.TestJob1 - Job nexe fire time: Thu Aug 16 11:56:00 CST 2018
11:56:00 [schedulerFactory_QuartzSchedulerThread] INFO com.scfire.springboot.quartzJob.TestJob1 - 构造方法1
11:56:00 [schedulerFactory_Worker-2] INFO com.scfire.springboot.quartzJob.TestJob1 - test job 1
11:56:00 [schedulerFactory_Worker-2] INFO com.scfire.springboot.quartzJob.TestJob1 - Job fired at Thu Aug 16 11:56:00 CST 2018
11:56:00 [schedulerFactory_Worker-2] INFO com.scfire.springboot.quartzJob.TestJob1 - Job nexe fire time: Thu Aug 16 11:56:20 CST 2018

另一个可能相关的配置

  详细的都东西写到配置文件中了,直接看吧

1
2
3
4
5
6
7
8
9
quartz.properties 下

# 单位毫秒级 简单意思就是超过1分钟的任务就抛弃不做了 根据业务需求配置 下面是详细解释
# 这个东西设置了以后就是超时1min的就不执行,小于1min会立即执行
# 设置15s的情况下,如果在10:00:00执行了一个任务,下次就是15s,但是如果服务器挂掉
# 然后在10:00:50重新启动服务器,由于任务间隔是15s,所以从00-50s中间会有三个任务超时没有执行(本来应该分别是在15s,30s,45s执行)
# 而超时的时间均小于1min,所以服务器启动以后会立即开启三个quartz线程来执行超时的任务。
# 如果设置1min,无论如何超时,都是超过1min的,所以不会执行超时任务。
#org.quartz.jobStore.misfireThreshold = 60000