Quartz Enterprise Scheduler:自行调度的作业

发布于 2024-10-14 23:58:41 字数 4061 浏览 6 评论 0原文

我正在使用 Quartz Enterprise Job Scheduler (1.8.3)。作业配置来自多个 xml 文件,我们有一个特殊的作业来检测这些 xml 文件中的更改并重新安排作业。这很有效,但问题是我还需要这个“调度程序作业”来重新调度它自己。一旦该作业出于某种原因重新安排自身,我就会看到它被执行了很多次。不过,我没有看到任何例外。

我已经复制并隔离了该问题。这将是入口点:

public class App {
    public static void main(final String[] args) throws ParseException, SchedulerException {
    // get the scheduler from the factory
    final Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

    // start the scheduler
    scheduler.start();

    // schedule the job to run every 20 seconds
    final JobDetail jobDetail = new JobDetail("jobname", "groupname", TestJob.class);        
    final Trigger trigger = new CronTrigger("triggername", "groupname", "*/20 * * * * ?");

    // set the scheduler in the job data map, so the job can re-configure itself
    jobDetail.getJobDataMap().put("scheduler", scheduler);

    // schedule job
    scheduler.scheduleJob(jobDetail, trigger);

    }
}

这将是作业类:

public class TestJob implements Job {

private final static Logger LOG = Logger.getLogger(TestJob.class);
private final static AtomicInteger jobExecutionCount = new AtomicInteger(0);

public void execute(final JobExecutionContext context) throws JobExecutionException {
    // get the scheduler from the data map
    final Scheduler scheduler = (Scheduler) context.getJobDetail().getJobDataMap().get("scheduler");
    LOG.info("running job! " + jobExecutionCount.incrementAndGet());

    // buid the job detail and trigger
    final JobDetail jobDetail = new JobDetail("jobname", "groupname", TestJob.class);
    // this time, schedule it to run every 35 secs
    final Trigger trigger;
    try {
        trigger = new CronTrigger("triggername", "groupname", "*/50 * * * * ?");
    } catch (final ParseException e) {
        throw new JobExecutionException(e);
    }
    trigger.setJobName("jobname");
    trigger.setJobGroup("groupname");

    // set the scheduler in the job data map, so this job can re-configure itself
    jobDetail.getJobDataMap().put("scheduler", scheduler);

    try {
        scheduler.rescheduleJob(trigger.getName(), jobDetail.getGroup(), trigger);
    } catch (final SchedulerException e) {
        throw new JobExecutionException(e);
    }
}
}

我已经尝试过使用 scheduler.rescheduleJobscheduler.deleteJob 然后使用 scheduler。调度作业。无论我做什么,这都是我得到的输出(我使用的是 log4j):

23:22:15,874         INFO SchedulerSignalerImpl:60 - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
23:22:15,878         INFO QuartzScheduler:219 - Quartz Scheduler v.1.8.3 created.
23:22:15,883         INFO RAMJobStore:139 - RAMJobStore initialized.
23:22:15,885         INFO QuartzScheduler:241 - Scheduler meta-data: Quartz Scheduler (v1.8.3) 

'MyScheduler' with instanceId '1'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

23:22:15,885         INFO StdSchedulerFactory:1275 - Quartz scheduler 'MyScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
23:22:15,886         INFO StdSchedulerFactory:1279 - Quartz scheduler version: 1.8.3
23:22:15,886         INFO QuartzScheduler:497 - Scheduler MyScheduler_$_1 started.
23:22:20,018         INFO TestJob:26 - running job! 1
23:22:50,004         INFO TestJob:26 - running job! 2
23:22:50,010         INFO TestJob:26 - running job! 3
23:22:50,014         INFO TestJob:26 - running job! 4
23:22:50,016         INFO TestJob:26 - running job! 5
...
23:22:50,999         INFO TestJob:26 - running job! 672
23:22:51,000         INFO TestJob:26 - running job! 673

请注意,在 23:22:20,018,作业运行良好。此时,作业会重新安排自己每 50 秒运行一次。下次运行时(23:22:50,004),它会被调度数百次。

关于如何在执行作业时配置作业的任何想法?我做错了什么?

谢谢!

I am using Quartz Enterprise Job Scheduler (1.8.3). The job configuration comes from several xml files and we have a special job that detects changes in these xml files and re-schedules jobs. This works dandy, but the problem is that I also need this "scheduler job" to re-schedule itself. Once this job re-schedules itself, for some reason, I see that it gets executed many times. I don't see any exceptions, though.

I have replicated and isolated the problem. This would be the entry-point:

public class App {
    public static void main(final String[] args) throws ParseException, SchedulerException {
    // get the scheduler from the factory
    final Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

    // start the scheduler
    scheduler.start();

    // schedule the job to run every 20 seconds
    final JobDetail jobDetail = new JobDetail("jobname", "groupname", TestJob.class);        
    final Trigger trigger = new CronTrigger("triggername", "groupname", "*/20 * * * * ?");

    // set the scheduler in the job data map, so the job can re-configure itself
    jobDetail.getJobDataMap().put("scheduler", scheduler);

    // schedule job
    scheduler.scheduleJob(jobDetail, trigger);

    }
}

And this would be the job class:

public class TestJob implements Job {

private final static Logger LOG = Logger.getLogger(TestJob.class);
private final static AtomicInteger jobExecutionCount = new AtomicInteger(0);

public void execute(final JobExecutionContext context) throws JobExecutionException {
    // get the scheduler from the data map
    final Scheduler scheduler = (Scheduler) context.getJobDetail().getJobDataMap().get("scheduler");
    LOG.info("running job! " + jobExecutionCount.incrementAndGet());

    // buid the job detail and trigger
    final JobDetail jobDetail = new JobDetail("jobname", "groupname", TestJob.class);
    // this time, schedule it to run every 35 secs
    final Trigger trigger;
    try {
        trigger = new CronTrigger("triggername", "groupname", "*/50 * * * * ?");
    } catch (final ParseException e) {
        throw new JobExecutionException(e);
    }
    trigger.setJobName("jobname");
    trigger.setJobGroup("groupname");

    // set the scheduler in the job data map, so this job can re-configure itself
    jobDetail.getJobDataMap().put("scheduler", scheduler);

    try {
        scheduler.rescheduleJob(trigger.getName(), jobDetail.getGroup(), trigger);
    } catch (final SchedulerException e) {
        throw new JobExecutionException(e);
    }
}
}

I've tried both with scheduler.rescheduleJob and with scheduler.deleteJob then scheduler.scheduleJob. No matter what I do, this is the output I get (I'm using log4j):

23:22:15,874         INFO SchedulerSignalerImpl:60 - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
23:22:15,878         INFO QuartzScheduler:219 - Quartz Scheduler v.1.8.3 created.
23:22:15,883         INFO RAMJobStore:139 - RAMJobStore initialized.
23:22:15,885         INFO QuartzScheduler:241 - Scheduler meta-data: Quartz Scheduler (v1.8.3) 

'MyScheduler' with instanceId '1'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

23:22:15,885         INFO StdSchedulerFactory:1275 - Quartz scheduler 'MyScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
23:22:15,886         INFO StdSchedulerFactory:1279 - Quartz scheduler version: 1.8.3
23:22:15,886         INFO QuartzScheduler:497 - Scheduler MyScheduler_$_1 started.
23:22:20,018         INFO TestJob:26 - running job! 1
23:22:50,004         INFO TestJob:26 - running job! 2
23:22:50,010         INFO TestJob:26 - running job! 3
23:22:50,014         INFO TestJob:26 - running job! 4
23:22:50,016         INFO TestJob:26 - running job! 5
...
23:22:50,999         INFO TestJob:26 - running job! 672
23:22:51,000         INFO TestJob:26 - running job! 673

Notice how at 23:22:20,018, the job runs fine. At this point, the job re-schedules itself to run every 50 seconds. The next time it runs (at 23:22:50,004), it gets scheduled hundreds of times.

Any ideas on how to configure a job while executing that job? What am I doing wrong?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如梦初醒的夏天 2024-10-21 23:58:41

简单的。

首先,您对 Cron 表达式有一些误解。 “*/20 * * * * ?”正如注释所暗示的那样,每二十秒一次,但这只是因为 60 可以被 20 整除。“/50 ...”不是每五十秒一次。是每分钟的第 0 秒和第 50 秒。另一个例子,“/13 ...”是每分钟的第 0、13、26、39 和 52 秒 - 所以在第 52 秒和下一分钟的 0 秒之间,只有 8 秒,而不是 13 秒因此,使用 */50,您将在每次发射之间间隔 50 秒,在其他发射之间间隔 10 秒。

然而,这并不是你迅速被解雇的原因。问题是当前秒是“50”,并且您正在安排新触发器在第二个“50”上触发,因此它会立即触发。然后仍然是第 50 秒,作业再次执行,并安排另一个触发器在第 50 秒触发,依此类推,在第 50 秒期间尽可能多次。

您需要将触发器的开始时间设置为未来(至少一秒),否则如果计划与当前秒匹配,它将在您安排它的同一秒触发。

另外,如果您确实需要每“N”秒类型的计划,我建议使用 SimpleTrigger 而不是 CronTrigger。 SimpleTrigger 可以“每 35 秒”或“每 50 秒”执行一次,没有问题。 CronTrigger 适用于“一月每个星期一 10 点钟第 15 和 45 分钟的第 0、15、40 和 43 秒”这样的表达式。

Easy.

First off you have a couple misunderstandings about Cron Expressions. "*/20 * * * * ?" is every twenty seconds as the comment implies, but only because 60 is evenly divisible by 20. "/50 ..." is not every fifty seconds. it is seconds 0 and 50 of every minute. As another example, "/13 ..." is seconds 0, 13, 26, 39, and 52 of every minute - so between second 52 and the next minute's 0 second, there is only 8 seconds, not 13. So with */50 you'll get 50 seconds between every other firing, and 10 seconds between the others.

That however is not the cause of your rapid firing of the job. The problem is that the current second is "50" and you are scheduling the new trigger to fire on second "50", so it immediately fires. And then it is still second 50, and the job executes again, and it schedules another trigger to fire on second 50, and so on, as many times as it can during the 50th second.

You need to set the trigger's start time into the future (at least one second) or it will fire on the same second you are scheduling it, if the schedule matches the current second.

Also if you really need every "N" seconds type of schedule, I suggest SimpleTrigger rather than CronTrigger. SimpleTrigger can do "every 35 seconds" or "every 50 seconds" no problem. CronTrigger is meant for expressions like "on seconds 0, 15, 40 and 43 of minutes 15 and 45 of the 10 o'clock hour on every Monday of January".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文