石英调度程序突然停止运行且没有异常错误。

28

我有一些石英定时任务,每天晚上7点运行。突然间它没有运行。我检查了我的server.log文件,并没有抛出任何异常。有人知道可能是什么问题吗?

提前感谢。


你能否发布一些用于配置Quartz作业的代码? - Boris Pavlović
有什么解决方法吗?我也遇到了同样的问题。 - kaptan
6个回答

15

我曾经遇到过类似的问题,但问题在于我在Quartz属性中设置了10个线程作为默认线程数。当我进行线程转储(thread dump)时,我发现有10个作业处于阻塞状态,这意味着我无法再运行更多的线程。

解决这个问题的快速方法是增加Quartz属性中的线程池中线程数。

实际的解决方法是检查我的代码,找出为什么会有10个阻塞的线程。

*要进行线程转储,您可以使用kill -3 <Java进程号>,这将在应用程序标准输出中打印线程转储信息,例如如果您正在运行Tomcat,则可以在catalina.out日志文件中找到它。


8

在我的情况下,我有一个打开的数据库连接。当没有更多可用的连接时,我的线程将永远等待。由于我无法启动任何其他作业,所以什么也没发生,一切都被阻塞了。 我的建议是检查是否有任何需要释放的阻塞资源。


在我们的情况下,当连接丢失时发生了这种情况。 - Davut Gürbüz

4
如果您正在使用数据库来存储作业,请检查触发器的trigger_state。目前我看到一个类似的问题(或者至少有相似的症状)。
每分钟运行一次的作业会将触发器留在“ACQUIRED”状态,然后再也不会运行。和您一样,我在日志中看不到任何信息。
我还看到同样问题的另一个原因。同样地,作业停止了运行,但是触发器并不处于“ACQUIRED”状态。到目前为止,我不知道原因。
我目前所知道的是,调度程序线程正在等待空闲的工作线程。看起来所有工作线程都在等待信号量以便更新它们的计划。我还没有能够获取线程转储以验证工作线程正在等待什么。
我正在运行Quartz 1.6.1 RC1。请参阅此错误报告:http://jira.opensymphony.com/browse/QUARTZ-668 我认为这就是我所看到的情况。

2

检查是否有任何作业抛出异常。将您的作业执行代码放在try catch块中,并跟踪任何异常以排除问题。


1

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

Assuming you use a Cron scheduler like the following way i will provide a detailed example

this is the SimpleJob class

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());
    }

}

This is your main class

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();
    }
}

The below cron expression means At second :10, every 5 minutes starting at minute :10, of every hour.

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

If you notice the most interesting part here is the

withMisfireHandlingInstructionFireAndProceed()

This is the key to solve your problem if your trigger is felt in a misfire situation, it instructs your scheduler to be fired immediately. An alternative occasion is to use

withMisfireHandlingInstructionDoNothing()

where upon a mis-fire situation the cronTrigger will be next fired at the started time which the scheduler is set on. For example in our case in At second :10, every 5 minutes starting at minute :10, of every hour.


0

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

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

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

我在应用程序服务器启动时启动调度程序。如果出现问题,则停止工作。然后我就没有任何机会再次启动它们。

我认为,如果我通过调用某些jsp请求来使用init servlet重新启动调度程序,这将产生差异。这将类似于查看配置文件(我们调度程序的健康状况并重新启动它们)。如果您有更好的启动调度程序的方法,请告诉我。


2
如果你的作业运行良好一段时间,那么问题不应该在于你如何启动调度程序。我猜你应该获取一个线程和堆转储并查看它卡在哪里。此外,值得注意的是开发环境和生产环境之间的差异,但首先从线程转储开始。 - aishwarya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接