quartz cron 表达式触发作业不遵守失火策略

问题描述 投票:0回答:1

在我们的后台库中,我们通过工厂方法创建触发器

 public Trigger buildTrigger(final JobDescription jobDescription) {
        final JobDescription.TriggerType triggerType = jobDescription.getTriggerType();
        if (triggerType == null) {
            throw new IllegalArgumentException("trigger type can not be empty");
        }
        return switch (triggerType) {
            case CRON -> makeCronTrigger(jobDescription);
            case ONCE -> makeOnceTrigger(jobDescription);
            case MULTIPLE_TIMES -> makeMultipleTimesTrigger(jobDescription);
            case LOOP -> makeLoopTrigger(jobDescription);
        };
    }
private CronScheduleBuilder createCronSchedule(JobDescription jobDescription) {
        CronScheduleBuilder cronSchedule = null;
        MisfirePolicy misfirePolicy = jobDescription.getMisfirePolicy() != null ? jobDescription.getMisfirePolicy() : MisfirePolicy.None;
        switch (misfirePolicy) {
            case DoNothing:
                cronSchedule = cronSchedule(jobDescription.getCronExpression()).withMisfireHandlingInstructionDoNothing();
                break;
            case FireAndProceed:
                cronSchedule = cronSchedule(jobDescription.getCronExpression()).withMisfireHandlingInstructionFireAndProceed();
                break;
            case IgnoreMisfires:
                cronSchedule = cronSchedule(jobDescription.getCronExpression()).withMisfireHandlingInstructionIgnoreMisfires();
                break;
            default:
                cronSchedule = cronSchedule(jobDescription.getCronExpression());
        }
        return cronSchedule;
    }

    private Trigger makeCronTrigger(final JobDescription jobDescription) {
        final TriggerBuilder<CronTrigger> cronTriggerTriggerBuilder = newTrigger()
                .withIdentity(jobDescription.getJobId())
                .withSchedule(createCronSchedule(jobDescription))
                .withPriority(getPriorityValue(jobDescription));
        setIdentity(jobDescription, cronTriggerTriggerBuilder);
        return cronTriggerTriggerBuilder.build();
    }

在我们的功能性微服务中,我们构建了将利用触发器的作业

@Bean
    @ConditionalOnProperty(prefix = "tickets.background.job", name = "deliver-tickets.enabled", havingValue = "true")
    JobDescription deliverTicketsJobDescription() {
        final long now = metrics ? System.currentTimeMillis() : 0;
        JobDescription jobDescription =  JobDescriptionBuilder.builder()
                .triggerType(TriggerType.CRON)
                .jobClass(DeliverTicketsJob.class)
                .cronExpression(deliverTicketsCron) // 0/5 * * * * ?
                .misfirePolicy(MisfirePolicy.FireAndProceed)
                .jobGroupId(jobGroupId)
                .jobId("deliverTickets")
                .build();
        if (metrics) {
            LOGGER.debug("METRIC: deliverTicketsJobDescription ~ duration: " + (System.currentTimeMillis() - now) + "ms");
        }
        return jobDescription;
    }

我们还将misfireThreshold 设置为1 秒

public class TicketApplication {
    static {
        System.setProperty("quartz.jobStore.misfireThreshold", "1000");
    }

我已经通过查看 qrtz_triggers 表并查看我们的工作和 Misfire_instruction 列集进行了验证。

但是从我的角度来看,处理失火的行为永远不会改变,它始终是:

  1. 启动时,失火的作业将立即连续启动两次
  2. 此后它将恢复正常,在本例中每 5 秒触发一次
  3. 我通过断点或 thread.sleep 将作业延迟 20 秒
  4. 从延迟恢复后,作业将连续执行多次,直到赶上
  5. 此时它会恢复按计划进行,每 5 秒一次

对我来说,这些步骤说明了失火的处理方法。从启动时(从关闭时)以及作业花费的时间长于间隔时开始失火。失败作业的执行应该通过分配的

MisfireHandlingInstruction
来控制,但就像我说的,它对上面列出的步骤的结果没有影响,我尝试了所有这些。

java quartz-scheduler
1个回答
0
投票

我已经恢复了quartz.jobStore.misfireThreshold。重新设计了该作业,以便在有添加/更新操作时手动触发。这使我能够将间隔重新配置为 2 分钟而不是 5 秒。 通过这种方式配置,我们确实看到了轻微的变化,所以我想它正在工作......

© www.soinside.com 2019 - 2024. All rights reserved.