quartz定时任务不执行(任务统筹策略)

由于某种原因,例如应用停掉,导致定时任务错过了本该执行的时间点,这就是定时任务过期。对于过期的定时任务,我们需要基于某种策略对其进行处理。过期策略在Trigger接口中定义了两种过期策略,publicstaticfinalintMISFIRE_INSTRUCTION_SMART_POLICY=0;publicstaticfinalintMISF…

大家好,又见面了,我是你们的朋友全栈君。

由于某种原因,例如应用停掉,导致定时任务错过了本该执行的时间点,这就是定时任务过期。对于过期的定时任务,我们需要基于某种策略对其进行处理。

过期策略

在Trigger接口中定义了两种过期策略,

    public static final int MISFIRE_INSTRUCTION_SMART_POLICY = 0;
    
    public static final int MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1;

MISFIRE_INSTRUCTION_SMART_POLICY 表明过期的定时任务将使用智能策略,如何处理将依赖于具体的Trigger实现类。等会我们会专门分析最常用的CronTrigger的智能过期策略的实现。
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 表明对于过期的定时任务将不执行任何过期策略。

设定过期策略

以CronTrigger为例,我们在添加定时任务的时候可以通过CronSchedulerBuilder设定过期策略。

 JobDetail jobDetail = JobBuilder.newJob(PrintJob.class)
                .storeDurably(true)
                .withIdentity(id)
                .withDescription(desc)
                .setJobData(jobDataMap).build();

CronScheduleBuilder schBuilder = CronScheduleBuilder.cronSchedule(cron)
.withMisfireHandlingInstructionFireAndProceed();

Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(id)
                .withDescription(desc)
                .forJob(jobDetail)
                .withSchedule(schBuilder).build();

如果不指定默认就是MISFIRE_INSTRUCTION_SMART_POLICY ,即采用智能策略模式。

CronTrigger过期策略

CronTrigger的智能过期策略有两种

public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1;
public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2;

看字面意思很好理解,第一种是立即触发一次,第二种是忽略掉不管。定时任务过期后,需要对triiger进行处理,具体的处理是在具体的Trigger实现类中实现的,例如CronTriggerImpl

@Override
    public void updateAfterMisfire(org.quartz.Calendar cal) { 
   
        int instr = getMisfireInstruction();

        if(instr == Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY)
            return;

        if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) { 
   
            instr = MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;
        }

        if (instr == MISFIRE_INSTRUCTION_DO_NOTHING) { 
   
            Date newFireTime = getFireTimeAfter(new Date());
            while (newFireTime != null && cal != null
                    && !cal.isTimeIncluded(newFireTime.getTime())) { 
   
                newFireTime = getFireTimeAfter(newFireTime);
            }
            setNextFireTime(newFireTime);
        } else if (instr == MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) { 
   
            setNextFireTime(new Date());
        }
    }

从源码中可以看到,CronTrigger的默认智能策略就是立即触发一次(MISFIRE_INSTRUCTION_FIRE_ONCE_NOW),即更新下次触发时间为当前时间。

过期定时任务检测

前半部分我们讲了定时任务的过期策略,并以CronTrigger为例,说明了其智能过期策略是如何实现的。后半部分,我们将视角从Trigger提升到Scheduler,看看Quartz是如何检测出过期定时任务的。

在JobStoreSupport中有一个叫MisfireHandler的线程,它负责定期检测出那些过期的定时任务。我们来看看它是如何做的。

首先,我们要明确一个过期的标准。一个比较直观的想法就是,如果一个Trigger的下次触发时间在当前时间之前,那么这个定时任务肯定是过期了。但是我们为了给人家一个机会,可以通过减去一个值,稍稍把这个截止时间调前一点。这个值可以通过quartz.properties配置,默认是60000,即60秒。

org.quartz.jobStore.misfireThreshold: 10000

当然Trigger必须是WAITING状态下才行,非WAITING状态的Trigger表明定时任务正在处理,已经完成或者出错了。而且过期策略不是MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 。

有了这三个过期指标,过期的定时任务就好筛选了。我们去QRTZ_TRIGGERS表里面,把符合这三个条件的Trigger都筛选出来。

过期定时任务恢复

以MISFIRE_INSTRUCTION_FIRE_ONCE_NOW过期策略为例,拿到过期的Trigger后,根据过期策略,调用updateAfterMisfire()对其进行更新,包括设置下次触发时间,更新状态为WAITING。

处理完trigger后,MisfireHandler会立即向QuartzSchedulerThread发送信号,告诉有紧急任务达到。

if (recoverMisfiredJobsResult.getProcessedMisfiredTriggerCount() > 0) { 
   
          
  signalSchedulingChangeImmediately(recoverMisfiredJobsResult.getEarliestNewTime());
}

QuartzSchedulerThread接收到信号后,如果才刚刚开始扫描触发器则必定能扫描到这个触发器,所以不用做任何额外处理。如果已经获取过触发器了,则释放掉已经获取的触发器,重新开始扫描。

if(releaseIfScheduleChangedSignificantly(triggers, triggerTime)) { 
   
   break;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/128399.html原文链接:https://javaforall.net

赞 (1)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SSH 学习笔记[通俗易懂]

    SSH 学习笔记[通俗易懂]前言:一直对SSH的概念比较陌生,由此而惧怕SSH,因此找来部分博客进行学习,将一些重难点予以记录。文章目录1、SSH原理简介1、SSH原理简介SSH叫安全外壳协议(SecureShell),是一种加密的网络传输协议,可在不安全的网络中网络服务提供安全的传输环境。它通过在网络中创建安全隧道来实现SSH客户端和服务器之间的连接。SSH是一种协议,存在多种实现,既有商业实现,也有开源实现(OSSH,OpenSSH)。公钥:ssh-keygen是安全外壳(SSH)协议套件

    2022年6月24日
  • WebRTC直播技术方案「建议收藏」

    WebRTC直播技术方案「建议收藏」我们都知道,WebRTC是面向互联网的一种即时通信标准,由于被Chrome、火狐、Safari等主流浏览器支持,并提供了一致和简洁的API,使得开发WebRTC的视频通信应用非常简单和流行。在大多数情况下,我们认为双向视频通信技术和视频直播技术是两种不同的技术,一个做视频通话,一个做单向直播(在以往的直播方案中,绝大部分是采用rtmp协议做直播上行的)。有没有可能使用WebR…

    2022年7月21日
  • maven工程配置私库「建议收藏」

    maven工程配置私库「建议收藏」为什么要配置私库?从中央仓库下载速度缓慢,而且有些jar包是公司私有的包不存在在中央仓库当中,所以我们需要配置私库。首先去修改setting文件,在maven文件夹下的conf文件夹当中<?xmlversion=”1.0″encoding=”UTF-8″?><settingsxmlns=”http://maven.apache.org/SETTINGS/1.0.0″…

    2022年7月18日
  • Ntp校时客户端小工具

    Ntp校时客户端小工具Ntp校对时间是常用的计算机时间同步的方式之一,但是网上偏偏下载不到一个不带广告,且操作简单暴力的软件,其实我要的功能无非就是1:开机自动校对时间2:每隔一段时间校对时间3:可配置ntp服务器地址和校对间隔但是就是找不到一款合适自己用的工具,无奈啊,只好自己手写一个配置文件是ini,一看就懂软件下载地址:https://download.csdn.net/download/li…

    2022年6月25日
  • Tomcat遇到”Error listenerStart”或”Error filterStart”问题且无详细日志时的log配置….

    Tomcat遇到”Error listenerStart”或”Error filterStart”问题且无详细日志时的log配置….昨天部署web应用到Tomcat之后,无法成功启动,并且控制台没有详细的错误信息,顶多就两行提示信息,例如:严重:ErrorlistenerStart严重:Context[/lizongbo]startupfailedduetopreviouserrors或者严重:ErrorfilterStartorg.apache.catalina.core.StandardCo…

    2022年7月27日
  • Html动态点击按钮实现“+”和“-”功能

    Html动态点击按钮实现“+”和“-”功能  Html动态点击按钮实现“+”和“-”功能&lt;!DOCTYPE html&gt;&lt;html lang="en"&gt; &lt;head&gt; &lt;meta http-equiv="Content-Type" content="text/html;"&gt; &lt;title&gt;html动态实现加减&lt;

    2022年6月13日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号