【问题标题】:Quartz Scheduler suddenly stop running and no exception errorQuartz Scheduler突然停止运行并且没有异常错误
【发布时间】:2010-10-11 17:19:19
【问题描述】:

我有一些石英作业,每天晚上 7 点运行。突然跑不起来了。我检查了我的 server.log 并且没有抛出异常。有人知道可能是什么问题吗?

提前致谢

【问题讨论】:

  • 您能发布一些用于配置石英作业的代码吗?
  • 任何解决方法?我也有同样的问题。

标签: java quartz-scheduler


【解决方案1】:

如果您使用数据库来存储作业,请检查触发器的 trigger_state。现在我看到了类似的问题(或者至少有类似的症状)。

每分钟运行一次的作业会使触发器处于“已获取”状态,并且永远不会再次运行。和你一样,我在日志中什么也没看到。

我还看到了导致同一问题的不同原因。同样,作业只是停止运行,但触发器未处于“ACQUIRED”状态。目前还不知道是什么原因。

到目前为止,我所知道的是调度程序线程正在等待一个空闲的工作线程。看起来所有的工作线程都在等待一个信号量来更新他们的日程安排。我还无法获得线程转储来验证工作线程正在等待什么。

我正在运行 Quartz 1.6.1 RC1。请参阅此错误报告:http://jira.opensymphony.com/browse/QUARTZ-668

我想这就是我所看到的。

【讨论】:

    【解决方案2】:

    检查是否有任何作业抛出异常。将您的 Job exe 代码放入 try catch 阻止跟踪任何异常以解决问题。

    【讨论】:

      【解决方案3】:

      我有一个类似的问题,但问题是,我有 10 个线程,石英属性中的默认线程数,当我进行线程转储*时,我发现我在 blocked stat 中有 10 个作业,这意味着我不能再运行任何线程了。

      快速修复此问题以增加石英属性中线程池中的线程数。

      实际的修复是检查我的代码以了解为什么我有 10 个阻塞线程。

      *要进行线程转储,您可以使用kill -3 将线程转储打印到您的应用程序标准输出,即如果您运行tomcat,您可以在catalina 中找到它。输出日志文件

      【讨论】:

        【解决方案4】:

        我有类似但有些不同的问题。我的调度程序在开发环境中运行良好。在这个调度程序中,我正在执行更新事务等工作。

        当我们将构建转移到生产环境时,调度程序运行良好,一切都很好,直到周六。星期六我的调度程序突然停止了。我没有发现任何与我的应用服务器 (OC4J) 中的调度程序相关的异常。

        我使用的是quartz-1.5.2 版本。我无法追踪问题的实际根本原因。

        我在应用程序服务器启动时启动调度程序。如果出现问题,它就会停止工作。那我就没有机会启动它们了。

        我认为,如果我再次使用一些 jsp 请求调用 init servlet 来启动调度程序,那么情况会有所不同。这就像查看配置文件(我们的调度程序的健康状况并再次启动它们)。如果您有更好的方法来启动调度程序,请建议我。

        【讨论】:

        • 如果您的作业在一段时间内运行良好,那么它不应该与您如何启动调度程序有关。我想你应该采取一个线程和堆转储,看看它卡在哪里。 dev 和 prod 设置之间的区别也毫无价值,但从线程转储开始。
        【解决方案5】:

        在我的例子中,我有一个与数据库的开放连接。当我没有更多可用的连接时,我的线程一直在等待。由于我无法开始任何其他工作,所以什么都没有发生,一切都被阻止了。 我的建议是让您检查是否有任何可能需要释放的阻塞资源。

        【讨论】:

        • 在我们的例子中,它发生在发生连接丢失时
        【解决方案6】:

        我遇到了类似的问题,不幸的是,以上答案都没有帮助我找出问题所在。我使用的是quartz-2.3.2 版本。首先,我同意其他一些人的观点,其中大多数情况下调度程序没有启动,是由于线程竞争条件阻塞并尝试从进入临界区的线程获取标志而没有释放它。这简直是​​一种糟糕的代码,但无论如何,我不想再像其他人一样说同样的话。我想提出我的解决方案,为您提供解决问题的方法。

        假设您使用如下方式的 Cron 调度程序,我将提供一个详细的示例

        这是 SimpleJob 类

        import org.quartz.Job;
        import org.quartz.JobExecutionContext;
        import org.quartz.JobExecutionException;
        import org.quartz.JobKey;
        import org.slf4j.Logger;
        import org.slf4j.LoggerFactory;
        
        import java.util.Date;
        
        public class SimpleJob implements Job {
        
            private static Logger _log = LoggerFactory.getLogger(SimpleJob.class);
        
            public SimpleJob() {
            }
        
            public void execute(JobExecutionContext context)
                    throws JobExecutionException {
        
                // This job simply prints out its job name and the
                // date and time that it is running
                JobKey jobKey = context.getJobDetail().getKey();
                _log.info("SimpleJob says: " + jobKey + " executing at " + new Date());
            }
        
        }
        

        这是你的主要课程

        import org.quartz.CronTrigger;
        import org.quartz.JobDetail;
        import org.quartz.Scheduler;
        import org.quartz.impl.StdSchedulerFactory;
        import org.slf4j.Logger;
        import org.slf4j.LoggerFactory;
        
        import static org.quartz.CronScheduleBuilder.cronSchedule;
        import static org.quartz.JobBuilder.newJob;
        import static org.quartz.TriggerBuilder.newTrigger;
        
        public class CronTriggerExample {
        
            public void run() throws Exception {
                Logger log = LoggerFactory.getLogger(CronTriggerExample.class);
        
                log.info("------- Initializing -------------------");
        
                // First we must get a reference to a scheduler
                JobDetail job = newJob(SimpleJob.class)
                        .withIdentity("job1", "group1").build();
        
                CronTrigger trigger = newTrigger()
                    .withIdentity("trigger1", "group1")
                    .withSchedule(cronSchedule("10 10/5 * ? * *").withMisfireHandlingInstructionFireAndProceed())
                    .build();
                Scheduler scheduler = new StdSchedulerFactory().getScheduler();
                scheduler.start();
                scheduler.scheduleJob(job, trigger);
            }
        
            public static void main(String[] args) throws Exception {
        
                CronTriggerExample example = new CronTriggerExample();
                example.run();
            }
        }
        

        下面的 cron 表达式表示在每秒 10 分钟,每 5 分钟开始,从每小时 10 分钟开始。

        cronSchedule("10 10/5 * ? * *")
        

        如果你注意到这里最有趣的部分是

        withMisfireHandlingInstructionFireAndProceed()
        

        如果您的触发器处于失火状态,这是解决问题的关键,它会指示您的调度程序立即被触发。另一种情况是使用

        withMisfireHandlingInstructionDoNothing()
        

        在发生错误触发的情况下,cronTrigger 将在调度程序设置的开始时间下一次触发。例如,在我们的案例中,在每秒 10 分钟,从每小时 10 分钟开始,每 5 分钟一次。

        【讨论】:

          猜你喜欢
          • 2019-03-12
          • 1970-01-01
          • 2021-01-08
          • 2020-11-09
          • 2016-12-18
          • 2015-07-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多