文章目录
前言
本文对JobCompleteHelper 工作内容进行介绍。
一、JobCompleteHelper 作用:
JobCompleteHelper是xxl-job-admin中的一个辅助类,主要用于处理任务执行完成后的相关操作。其作用包括:
-
标记任务执行完成:JobCompleteHelper负责在任务执行完成后对任务状态进行标记,通知xxl-job-admin任务执行成功,更新任务执行记录。
-
日志记录:记录任务执行完成的相关日志信息,包括执行结果、执行时间、消耗资源等,以便后续跟踪和分析。
-
处理任务回调:在任务执行完成后,JobCompleteHelper可能需要触发一些任务执行完成后的回调操作,比如发送通知、更新数据等。
-
监控任务执行状态:通过JobCompleteHelper,xxl-job-admin能够实时监控任务的执行情况,及时发现任务执行异常或超时等情况。
总的来说,JobCompleteHelper在xxl-job-admin中扮演着处理任务执行完成后相关操作的重要角色,确保任务执行成功并及时记录相关信息,提高任务执行的可靠性和监控能力。
二、JobCompleteHelper 源码内容:
2.1 start() 初始化方法:
2.1.1 任务执行日志回调线程池:
private static Logger logger = LoggerFactory.getLogger(JobCompleteHelper.class);
private static JobCompleteHelper instance = new JobCompleteHelper();
public static JobCompleteHelper getInstance(){
return instance;
}
// ---------------------- monitor ----------------------
private ThreadPoolExecutor callbackThreadPool = null;
private Thread monitorThread;
private volatile boolean toStop = false;
public void start(){
// for callback 初始化 日志回调线程池,后续用于执行 执行器项目执行任务返回的 任务状态
callbackThreadPool = new ThreadPoolExecutor(
2,
20,
30L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(3000),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "xxl-job, admin JobLosedMonitorHelper-callbackThreadPool-" + r.hashCode());
}
},
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
r.run();
logger.warn(">>>>>>>>>>> xxl-job, callback too fast, match threadpool rejected handler(run now).");
}
});
}
2.1.2 monitorThread线程标记失效的任务:
// for monitor
monitorThread = new Thread(new Runnable() {
@Override
public void run() {
// wait for JobTriggerPoolHelper-init
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
}
// monitor
while (!toStop) {
try {
// 任务结果丢失处理:调度记录停留在 "运行中" 状态超过10min,
// 且对应执行器心跳注册失败不在线,则将本地调度主动标记失败;
Date losedTime = DateUtil.addMinutes(new Date(), -10);
// 获取已经被触发器触发(正在执行中),并且触发已经超过了10分钟,任务还没有执行完毕的;
// 并且任务没有触发器的 ;任务id 集合
/**
* SELECT
t.id
FROM
xxl_job_log t
LEFT JOIN xxl_job_registry t2 ON t.executor_address = t2.registry_value
WHERE
t.trigger_code = 200
AND t.handle_code = 0
AND t.trigger_time <![CDATA[ <= ]]> #{losedTime}
AND t2.id IS NULL;
**/
List<Long> losedJobIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findLostJobIds(losedTime);
if (losedJobIds!=null && losedJobIds.size()>0) {
for (Long logId: losedJobIds) {
XxlJobLog jobLog = new XxlJobLog();
jobLog.setId(logId);
jobLog.setHandleTime(new Date());
jobLog.setHandleCode(ReturnT.FAIL_CODE);
jobLog.setHandleMsg( I18nUtil.getString("joblog_lost_fail") );
// 标记任务为失效状态
XxlJobCompleter.updateHandleInfoAndFinish(jobLog);
}
}
} catch (Exception e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
}
}
try {
TimeUnit.SECONDS.sleep(60);
} catch (Exception e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
}
}
logger.info(">>>>>>>>>>> xxl-job, JobLosedMonitorHelper stop");
}
});
monitorThread.setDaemon(true);
monitorThread.setName("xxl-job, admin JobLosedMonitorHelper");
monitorThread.start();
2.2 callback 执行器执行任务后的回调:
public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {
// 交由 callbackThreadPool线程池执行任务
callbackThreadPool.execute(new Runnable() {
@Override
public void run() {
for (HandleCallbackParam handleCallbackParam: callbackParamList) {
// 执行任务
ReturnT<String> callbackResult = callback(handleCallbackParam);
logger.debug(">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}",
(callbackResult.getCode()== ReturnT.SUCCESS_CODE?"success":"fail"), handleCallbackParam, callbackResult);
}
}
});
return ReturnT.SUCCESS;
}
private ReturnT<String> callback(HandleCallbackParam handleCallbackParam) {
// valid log item 获取任务执行的日志
XxlJobLog log = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().load(handleCallbackParam.getLogId());
if (log == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "log item not found.");
}
// 任务是否已经被回调处理过了
if (log.getHandleCode() > 0) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "log repeate callback."); // avoid repeat callback, trigger child job etc
}
// handle msg
// 填充回调结果状态和信息 并更新日志对象
StringBuffer handleMsg = new StringBuffer();
if (log.getHandleMsg()!=null) {
handleMsg.append(log.getHandleMsg()).append("<br>");
}
if (handleCallbackParam.getHandleMsg() != null) {
handleMsg.append(handleCallbackParam.getHandleMsg());
}
// success, save log
log.setHandleTime(new Date());
log.setHandleCode(handleCallbackParam.getHandleCode());
log.setHandleMsg(handleMsg.toString());
XxlJobCompleter.updateHandleInfoAndFinish(log);
return ReturnT.SUCCESS;
}
2.3 toStop() 释放资源:
容器关闭是触发toStop() 方法,释放资源。
public void toStop(){
// 重置toStop 标识 使monitorThread 线程结束while 循环
toStop = true;
// stop registryOrRemoveThreadPool
// 日志回调线程 停止
callbackThreadPool.shutdownNow();
// stop monitorThread (interrupt and wait)
monitorThread.interrupt();
try {
// 等待monitorThread 线程任务结束
monitorThread.join();
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
总结
本文对JobCompleteHelper 工作内容进行介绍;