程序探活

2020-07-05  本文已影响0人  不存在的bug

背景:xxl-job定时跑批,本地创建专门线程监测定时任务是否执行了,防止xxl-job挂了,及时通知。

@Slf4j
@Component
public final class DetectSubcriber implements DisposableBean,Runnable {

    private static final SimpleDateFormat formatdate = new SimpleDateFormat("YYYY-MM-dd");
    private static final SimpleDateFormat formatTime = new SimpleDateFormat("HH:mm");

    private final Thread thread;
    public static volatile Date jobExecDate; //由xxl-job任务线程修改,执行过了的设置当前时间
    public static Boolean detectSelfExecFalg = true; //控制当前探测只发送一次提醒

    private String specifiedFinishTime;  //指定一个定时任务完成之后的时间点
    private Long detectIntervalTime; //探测间隔时间,没必要一直跑,合理即可

    private DetectSubcriber(@Value("${specified.finish.time}")String specifiedFinishTime,
                            @Value("${detect.interval.time}")Long detectIntervalTime,
                            @Autowired TeacherLiveJobHandler teacherLiveJobHandler){
        this.specifiedFinishTime = specifiedFinishTime;
        this.detectIntervalTime = detectIntervalTime;
        this.teacherLiveJobHandler = teacherLiveJobHandler;
        this.thread = new Thread(this);
        this.thread.setDaemon(true);
        this.thread.start();
    }

    @Override
    public void run() {

        try {
            final Date finishTime = formatTime.parse(specifiedFinishTime);
            while(true){

                Thread.sleep(detectIntervalTime); //应该先执行,防止系统启动之后就会触发探测报警
                final boolean jobNotExec = jobExecDate == null || !formatdate.format(jobExecDate).equals(formatdate.format(new Date()));
                final Date currentTime = formatTime.parse(formatTime.format(new Date()));

                if (currentTime.before(finishTime)) {
                    detectSelfExecFalg = true; //在该时间段开启
                }

                if (jobNotExec && detectSelfExecFalg && currentTime.after(finishTime)) {

                    detectSelfExecFalg = false; //在currentTime.after(finishTime)内执行一次就行
                    log.info("xxl-job未执行,触发探活执行。");
                    //xxl-job挂了,由当前线程触发
                    try {
                        //todo 触发定时
                    }catch (Exception e){
                        log.error("",e);
                    }

                    //todo 发送报警

                }

            }
        }catch (Exception e){
            if (specifiedFinishTime == null) {
                log.error("启动探活必须指定开始时间(探活开始时间的时间点)【specified.finish.time】。");
            }
            log.error("探活程序报错:",e);
        }

    }

    @Override
    public void destroy() throws Exception {
        jobExecDate = null;
    }

}

另一个线程:

DetectSubcriber.jobExecDate = new Date(); //应该先执行,下面任务的成功失败和探活无关。不能因为下面任务失败而导致触发探活报警。任务应该有自己的报警
 //todo 跑批核心任务        

写在后面

这个有必要吗?个人觉得没必要,本身xxl-job肯定是集群部署,故障率很低,万一要是发生了,那应该也是由运维人员及时修复。另一个发生故障的可能就是物理故障,如果都部署在同一台机器那也没啥毛用,不过一般是不会这么部署。同意这么做只是不想费口舌,再者是觉得这挺好玩。一些补偿措施不能为了甩锅而补偿。这程序可能几年也不会触发......

上一篇下一篇

猜你喜欢

热点阅读