文章目录
前言
本文对XxlJobExecutor 初始化内容进行介绍。
一、XxlJobExecutor作用:
XxlJobExecutor是一个任务调度执行器,通常用于快速集成分布式任务调度功能到项目中。它可以方便地实现定时任务、定时调度、分布式调度等功能。
具体来说,XxlJobExecutor是一个基于分布式任务调度平台xxl-job的执行器,可以与xxl-job平台进行通信,接收并执行任务。通过使用XxlJobExecutor,可以实现任务的动态添加、暂停、恢复、删除等操作,同时支持对任务执行日志进行管理和监控。
二、XxlJobExecutor 源码内容:
2.1 start() 方法
public void start() throws Exception {
// init logpath
// 执行器运行日志文件存储磁盘路径 赋值
XxlJobFileAppender.initLogPath(logPath);
// init invoker, admin-client
// 初始化服务器的地址与令牌
initAdminBizList(adminAddresses, accessToken);
// init JobLogFileCleanThread
// 日志删除
JobLogFileCleanThread.getInstance().start(logRetentionDays);
// init TriggerCallbackThread
// 任务的回调,告诉xxljob server 任务是否执行成功
TriggerCallbackThread.getInstance().start();
// init executor-server
// 执行器注册,开启netty 接收xxljob server 端任务的调用
initEmbedServer(address, ip, port, appname, accessToken);
}
2.2 initAdminBizList 初始化:
2.2.1 服务端访问对象AdminBiz 封装:
private static List<AdminBiz> adminBizList;
/**
接收服务端地址 及 通信的token 并包装成AdminBiz 对象,方便后续通过AdminBiz 向服务端发送http 请求
* adminAddresses : xxl.job.admin.addresses 配置地址 多个地址以 "," 分隔
* accessToken: xxl.job.accessToken配置的访问令牌
**/
private void initAdminBizList(String adminAddresses, String accessToken) throws Exception {
if (adminAddresses!=null && adminAddresses.trim().length()>0) {
// 以"," 分隔服务端的地址 并进行遍历
for (String address: adminAddresses.trim().split(",")) {
if (address!=null && address.trim().length()>0) {
// 封装成为AdminBiz 对象
AdminBiz adminBiz = new AdminBizClient(address.trim(), accessToken);
if (adminBizList == null) {
adminBizList = new ArrayList<AdminBiz>();
}
// 将 封装成好的 AdminBiz 钓友服务端的对象放入集合中
adminBizList.add(adminBiz);
}
}
}
}
2.2.2 AdminBiz 内容:
/**
* admin api test
*
* @author xuxueli 2017-07-28 22:14:52
*/
public class AdminBizClient implements AdminBiz {
public AdminBizClient() {
}
// 构造方法实例化 AdminBizClient 对象
public AdminBizClient(String addressUrl, String accessToken) {
this.addressUrl = addressUrl;
this.accessToken = accessToken;
// valid
if (!this.addressUrl.endsWith("/")) {
this.addressUrl = this.addressUrl + "/";
}
}
private String addressUrl ;
private String accessToken;
private int timeout = 3;
// 发送任务执行器情况 给服务端
@Override
public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {
return XxlJobRemotingUtil.postBody(addressUrl+"api/callback", accessToken, timeout, callbackParamList, String.class);
}
// 执行器项目启动后向 服务端发送执行器的地址,进行注册
@Override
public ReturnT<String> registry(RegistryParam registryParam) {
return XxlJobRemotingUtil.postBody(addressUrl + "api/registry", accessToken, timeout, registryParam, String.class);
}
// 执行器项目停止后向 服务端发送执行器的地址,服务端进行对应执行器的移除
@Override
public ReturnT<String> registryRemove(RegistryParam registryParam) {
return XxlJobRemotingUtil.postBody(addressUrl + "api/registryRemove", accessToken, timeout, registryParam, String.class);
}
}
2.3 JobLogFileCleanThread log 日志删除:
/**
* job file clean thread
*
* @author xuxueli 2017-12-29 16:23:43
*/
public class JobLogFileCleanThread {
// log 日志对象获取
private static Logger logger = LoggerFactory.getLogger(JobLogFileCleanThread.class);
// 实例化 JobLogFileCleanThread 对象
private static JobLogFileCleanThread instance = new JobLogFileCleanThread();
public static JobLogFileCleanThread getInstance(){
return instance;
}
// 声明清理日志文件的 线程
private Thread localThread;
// 理日志文件线程的 停止标识
private volatile boolean toStop = false;
// logRetentionDays xxl.job.executor.logretentiondays 配置的值 默认值30 天
public void start(final long logRetentionDays){
// limit min value
// 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能
if (logRetentionDays < 3 ) {
return;
}
// 清理日志线程
localThread = new Thread(new Runnable() {
@Override
public void run() {
while (!toStop) {
try {
// clean log dir, over logRetentionDays
// 获取配置的 xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler 路径下的目录文件
File[] childDirs = new File(XxlJobFileAppender.getLogPath()).listFiles();
if (childDirs!=null && childDirs.length>0) {
// today 获取今天的时间
Calendar todayCal = Calendar.getInstance();
todayCal.set(Calendar.HOUR_OF_DAY,0);
todayCal.set(Calendar.MINUTE,0);
todayCal.set(Calendar.SECOND,0);
todayCal.set(Calendar.MILLISECOND,0);
Date todayDate = todayCal.getTime();
for (File childFile: childDirs) {
// valid 文件不是目录则继续下一次循环
if (!childFile.isDirectory()) {
continue;
}
// 目录的名字不包含"-" 则继续下一次循环
if (childFile.getName().indexOf("-") == -1) {
continue;
}
// file create date
Date logFileCreateDate = null;
try {
// 根据文件的名字 获取 改文件是何时生成的
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
logFileCreateDate = simpleDateFormat.parse(childFile.getName());
} catch (ParseException e) {
logger.error(e.getMessage(), e);
}
if (logFileCreateDate == null) {
continue;
}
// 根据文件的生成时间是 判断是否在保留的天数之内
if ((todayDate.getTime()-logFileCreateDate.getTime()) >= logRetentionDays * (24 * 60 * 60 * 1000) ) {
// 删除日志文件
FileUtil.deleteRecursively(childFile);
}
}
}
} catch (Exception e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
}
try {
// 线程睡1天
TimeUnit.DAYS.sleep(1);
} catch (InterruptedException e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
}
}
logger.info(">>>>>>>>>>> xxl-job, executor JobLogFileCleanThread thread destroy.");
}
});
// 设置线程为守护线程,设置线程的名字,启动线程
localThread.setDaemon(true);
localThread.setName("xxl-job, executor JobLogFileCleanThread");
localThread.start();
}
// 当容器停止时 调用toStop() 方法 释放资源
public void toStop() {
// 重置清除日志线程的标识,使其跳出while 循环
toStop = true;
if (localThread == null) {
return;
}
// interrupt and wait
localThread.interrupt();
try {
// 等待 清理日志的localThread 线程 完成任务
localThread.join();
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
}
日志文件记录地址如下:
文件日志:
总结
本文对XxlJobExecutor 初始化时 执行器的封装以及 日志清理 内容进行介绍。