Quartz Enterprise Scheduler:スケジュール自体のジョブ
-
27-10-2019 - |
質問
Quartz Enterprise Job Scheduler(1.8.3)を使用しています。ジョブ構成はいくつかのXMLファイルからのものであり、これらのXMLファイルと再スケジュールのジョブの変更を検出する特別なジョブがあります。これはDandyに機能しますが、問題は、この「スケジューラジョブ」がそれ自体を再スケジュールするために必要なことです。このジョブがスケジュール自体を再スケジュールすると、何らかの理由で、何度も実行されることがわかります。ただし、例外はありません。
問題を複製して分離しました。これがエントリポイントになります:
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.rescheduleJob
と scheduler.deleteJob
それから scheduler.scheduleJob
. 。私が何をしても、これは私が得る出力です(私は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)、何百回もスケジュールされます。
ジョブの構成方法に関するアイデア その間 その仕事を実行しますか?私は何が間違っているのですか?
ありがとう!
解決
簡単。
まず、Cronの表現についての誤解がいくつかあります。 「 */20 * * *?」コメントが示唆するように20秒ごとにですが、60が20で均等に割り切れるからです。」/50 ...「50秒ごとではありません。毎分0と50です。別の例として、 "/13 ... "は秒0、13、26、39、および52分の52です。したがって、2番目の52と次の1分0秒の間に、13ではなく8秒しかありません。他のすべての発砲の間に50秒、他の射撃の間で10秒を取得します。
しかし、それはあなたの仕事の急速な解雇の原因ではありません。問題は、現在の秒が「50」であり、新しいトリガーが2番目の「50」で発射するようにスケジュールしているため、すぐに発砲することです。そして、それはまだ2番目の50であり、ジョブは再び実行され、50秒間にできる限り多くの場合、2番目の50で発砲する別のトリガーをスケジュールします。
トリガーの開始時間を未来に設定する必要があります(少なくとも1秒)、スケジュールが現在の秒と一致する場合、スケジュールするのと同じ秒で発火します。
また、すべての「n」秒タイプのスケジュールが必要な場合は、crontriggerではなくSimpleTriggerをお勧めします。 SimpleTriggerは、「35秒ごとに」または「50秒ごとに」問題ありません。 Crontriggerは、「1月の毎週月曜日の10時の15分の15分、15、40、45の秒」などの表現を目的としています。