xxl-job没有执行任务却每隔30秒报错

今天远程检查医院上线的系统运行状况时,发现xxl-job调度系统在没有执行任务的情况下一直报错,如下图:

看这发生时间,每30秒一次,特别有规律,一开始以为是有任务在执行,因为参数是json格式的字符串,封装的时候出错了导致转换时报错,但是检查了一遍所有的任务,都不在执行的时间区间。

于是停掉了整个调度任务服务,将日志改名后进行备份,重新启动,发现一启动服务就开始报错,这下可神奇了。

通过分析日志,异常发生在TriggerCallbackThread类中的238行,从gitee下载源码进行分析:

 private void retryFailCallbackFile(){
		/**
		 * 2、找到文件来源
		 * 这里根据路径拿到文件
		 */
        // valid
        File callbackLogPath = new File(failCallbackFilePath);
        if (!callbackLogPath.exists()) {
            return;
        }
        if (callbackLogPath.isFile()) {
            callbackLogPath.delete();
        }
        if (!(callbackLogPath.isDirectory() && callbackLogPath.list()!=null && callbackLogPath.list().length>0)) {
            return;
        }

        // load and clear file, retry
        for (File callbaclLogFile: callbackLogPath.listFiles()) {
            /**
             * 1、【发生异常的代码】
             * 这里是利用FileUtil文件工具类解析文件内容,那么应该可以猜测到文件的内容有问题了。
             * 那他是拿哪里的文件呢
             */
            byte[] callbackParamList_bytes = FileUtil.readFileContent(callbaclLogFile);
            
            List<HandleCallbackParam> callbackParamList = (List<HandleCallbackParam>) JdkSerializeTool.deserialize(callbackParamList_bytes, List.class);

            callbaclLogFile.delete();
            doCallback(callbackParamList);
        }

    }
/**
 * 3、找到文件路径
 * 这里还不能判断是那哪个路径下的文件,继续分析XxlJobFileAppender.getLogPath();
 */
	private static String failCallbackFilePath = XxlJobFileAppender.getLogPath().concat(File.separator).concat("callbacklog").concat(File.separator);
public class XxlJobFileAppender {

    private static String logBasePath = "/data/applogs/xxl-job/jobhandler";
    
    public static String getLogPath() {
		return logBasePath;
	}
}

发现拿的是/data/applogs/xxl-job/jobhandler/callbacklog/下的日志文件,这些日志文件从哪里来的,又是干什么用的呢?

原来是执行器终止的时候,会批量获取回调队列里的回调入参集合,如果回调入参集合不为空就会记录当前任务执行日志并生成日志文件。如果发生异常则会将回调入参集合序列号为byte[],然后在日志根目录下创建callbacklog目录,生成回调失败记录文件xxl-job-callback-{x}.log,将byte[]写入回调失败日志中进行保存。最后新建一个回调重试守护线程,每隔30秒执行一次。当执行器启动时,守护线程会去读失败日志将byte[]转为回调入参对象集合,如果没问题的话就会删除日志文件并重新执行回调方法。

所以问题就是,执行任务出现异常时将回调入参集合转为byte[]保存到回调日志中,后面再拿到回调日志转回byte[]的时候报错了。
于是,我就找到这个路径下的错误日志,全部delete掉,服务就正常了。

参考《RabbitsInTheGrass——分布式定时任务—xxl-job学习(二)——执行器的启动过程源码分析》

posted @ 2021-03-10 20:01  程序员微尘  阅读(3923)  评论(1编辑  收藏  举报