执行器新增配置项("xxl.job.executor.logretentiondays"):日志保存天数,执行器自动删除过期日志文件。限制配置最少保存3天,否则功能无效。

master
xuxueli 7 years ago
parent cceccc6276
commit dd94810416
  1. 1
      doc/XXL-JOB官方文档.md
  2. 12
      xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java
  3. 4
      xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/ScriptJobHandler.java
  4. 20
      xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobFileAppender.java
  5. 118
      xxl-job-core/src/main/java/com/xxl/job/core/thread/JobLogFileCleanThread.java
  6. 27
      xxl-job-core/src/main/java/com/xxl/job/core/util/FileUtil.java
  7. 6
      xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/applicationcontext-xxl-job.xml
  8. 7
      xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/xxl-job-executor.properties

@ -1112,6 +1112,7 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
- 28、新增"任务ID"属性,移除"JobKey"属性,前者承担所有功能,方便后续增强任务依赖功能。 - 28、新增"任务ID"属性,移除"JobKey"属性,前者承担所有功能,方便后续增强任务依赖功能。
- 29、任务循环依赖问题修复,避免子任务与父任务重复导致的调度死循环; - 29、任务循环依赖问题修复,避免子任务与父任务重复导致的调度死循环;
- 30、任务列表新增筛选条件 "任务描述",快速检索任务; - 30、任务列表新增筛选条件 "任务描述",快速检索任务;
- 31、执行器新增配置项("xxl.job.executor.logretentiondays"):日志保存天数,执行器自动删除过期日志文件。限制配置最少保存3天,否则功能无效。
### TODO LIST ### TODO LIST
- 1、任务权限管理:执行器为粒度分配权限,核心操作校验权限; - 1、任务权限管理:执行器为粒度分配权限,核心操作校验权限;

@ -8,6 +8,7 @@ import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobFileAppender; import com.xxl.job.core.log.XxlJobFileAppender;
import com.xxl.job.core.rpc.netcom.NetComClientProxy; import com.xxl.job.core.rpc.netcom.NetComClientProxy;
import com.xxl.job.core.rpc.netcom.NetComServerFactory; import com.xxl.job.core.rpc.netcom.NetComServerFactory;
import com.xxl.job.core.thread.JobLogFileCleanThread;
import com.xxl.job.core.thread.JobThread; import com.xxl.job.core.thread.JobThread;
import com.xxl.job.core.util.NetUtil; import com.xxl.job.core.util.NetUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -34,6 +35,7 @@ public class XxlJobExecutor implements ApplicationContextAware {
private String adminAddresses; private String adminAddresses;
private String accessToken; private String accessToken;
private String logPath; private String logPath;
private int logRetentionDays;
public void setIp(String ip) { public void setIp(String ip) {
this.ip = ip; this.ip = ip;
@ -53,7 +55,9 @@ public class XxlJobExecutor implements ApplicationContextAware {
public void setLogPath(String logPath) { public void setLogPath(String logPath) {
this.logPath = logPath; this.logPath = logPath;
} }
public void setLogRetentionDays(int logRetentionDays) {
this.logRetentionDays = logRetentionDays;
}
// ---------------------- applicationContext ---------------------- // ---------------------- applicationContext ----------------------
private static ApplicationContext applicationContext; private static ApplicationContext applicationContext;
@ -79,6 +83,9 @@ public class XxlJobExecutor implements ApplicationContextAware {
// init executor-server // init executor-server
initExecutorServer(port, ip, appName, accessToken); initExecutorServer(port, ip, appName, accessToken);
// init JobLogFileCleanThread
JobLogFileCleanThread.getInstance().start(logRetentionDays);
} }
public void destroy(){ public void destroy(){
// destory JobThreadRepository // destory JobThreadRepository
@ -91,6 +98,9 @@ public class XxlJobExecutor implements ApplicationContextAware {
// destory executor-server // destory executor-server
stopExecutorServer(); stopExecutorServer();
// destory JobLogFileCleanThread
JobLogFileCleanThread.getInstance().toStop();
} }

@ -40,8 +40,8 @@ public class ScriptJobHandler extends IJobHandler {
String cmd = glueType.getCmd(); String cmd = glueType.getCmd();
// make script file // make script file
String scriptFileName = XxlJobFileAppender.getLogPath() String scriptFileName = XxlJobFileAppender.getGlueSrcPath()
.concat("/gluesource/") .concat("/")
.concat(String.valueOf(jobId)) .concat(String.valueOf(jobId))
.concat("_") .concat("_")
.concat(String.valueOf(glueUpdatetime)) .concat(String.valueOf(glueUpdatetime))

@ -20,8 +20,21 @@ public class XxlJobFileAppender {
public static final InheritableThreadLocal<String> contextHolder = new InheritableThreadLocal<String>(); public static final InheritableThreadLocal<String> contextHolder = new InheritableThreadLocal<String>();
// log base path /**
* log base path
*
* strut like:
* ---/
* ---/gluesource/
* ---/gluesource/10_1514171108000.js
* ---/gluesource/10_1514171108000.js
* ---/2017-12-25/
* ---/2017-12-25/639.log
* ---/2017-12-25/821.log
*
*/
private static String logBasePath = "/data/applogs/xxl-job/jobhandler"; private static String logBasePath = "/data/applogs/xxl-job/jobhandler";
private static String glueSrcPath = logBasePath.concat("/gluesource");
public static void initLogPath(String logPath){ public static void initLogPath(String logPath){
// init // init
if (logPath!=null && logPath.trim().length()>0) { if (logPath!=null && logPath.trim().length()>0) {
@ -39,11 +52,14 @@ public class XxlJobFileAppender {
if (!glueBaseDir.exists()) { if (!glueBaseDir.exists()) {
glueBaseDir.mkdirs(); glueBaseDir.mkdirs();
} }
glueSrcPath = glueBaseDir.getPath();
} }
public static String getLogPath() { public static String getLogPath() {
return logBasePath; return logBasePath;
} }
public static String getGlueSrcPath() {
return glueSrcPath;
}
/** /**
* log filename, like "logPath/yyyy-MM-dd/9999.log" * log filename, like "logPath/yyyy-MM-dd/9999.log"

@ -0,0 +1,118 @@
package com.xxl.job.core.thread;
import com.xxl.job.core.log.XxlJobFileAppender;
import com.xxl.job.core.util.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* job file clean thread
*
* @author xuxueli 2017-12-29 16:23:43
*/
public class JobLogFileCleanThread extends Thread {
private static Logger logger = LoggerFactory.getLogger(JobLogFileCleanThread.class);
private static JobLogFileCleanThread instance = new JobLogFileCleanThread();
public static JobLogFileCleanThread getInstance(){
return instance;
}
private Thread localThread;
private volatile boolean toStop = false;
public void start(final long logRetentionDays){
// limit min value
if (logRetentionDays < 3 ) {
return;
}
localThread = new Thread(new Runnable() {
@Override
public void run() {
while (!toStop) {
try {
// clean log dir, over logRetentionDays
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) {
logger.error(e.getMessage(), e);
}
try {
TimeUnit.DAYS.sleep(1);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
logger.info(">>>>>>>>>>> xxl-job, executor JobLogFileCleanThread thread destory.");
}
});
localThread.setDaemon(true);
localThread.start();
}
public void toStop() {
toStop = true;
if (localThread == null) {
return;
}
// interrupt and wait
localThread.interrupt();
try {
localThread.join();
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
}

@ -0,0 +1,27 @@
package com.xxl.job.core.util;
import java.io.File;
/**
* file tool
*
* @author xuxueli 2017-12-29 17:56:48
*/
public class FileUtil {
public static boolean deleteRecursively(File root) {
if (root != null && root.exists()) {
if (root.isDirectory()) {
File[] children = root.listFiles();
if (children != null) {
for (File child : children) {
deleteRecursively(child);
}
}
}
return root.delete();
}
return false;
}
}

@ -31,10 +31,12 @@
<property name="appName" value="${xxl.job.executor.appname}" /> <property name="appName" value="${xxl.job.executor.appname}" />
<!-- 执行器注册中心地址[选填],为空则关闭自动注册 --> <!-- 执行器注册中心地址[选填],为空则关闭自动注册 -->
<property name="adminAddresses" value="${xxl.job.admin.addresses}" /> <property name="adminAddresses" value="${xxl.job.admin.addresses}" />
<!-- 执行器日志路径[选填],为空则使用默认路径 -->
<property name="logPath" value="${xxl.job.executor.logpath}" />
<!-- 访问令牌[选填],非空则进行匹配校验 --> <!-- 访问令牌[选填],非空则进行匹配校验 -->
<property name="accessToken" value="${xxl.job.accessToken}" /> <property name="accessToken" value="${xxl.job.accessToken}" />
<!-- 执行器日志路径[选填],为空则使用默认路径 -->
<property name="logPath" value="${xxl.job.executor.logpath}" />
<!-- 日志保存天数[选填],值大于3时生效 -->
<property name="logRetentionDays" value="${xxl.job.executor.logretentiondays}" />
</bean> </bean>

@ -6,8 +6,11 @@ xxl.job.executor.appname=xxl-job-executor-sample
xxl.job.executor.ip= xxl.job.executor.ip=
xxl.job.executor.port=9999 xxl.job.executor.port=9999
### xxl-job, access token
xxl.job.accessToken=
### xxl-job log path ### xxl-job log path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job log retention days
xxl.job.executor.logretentiondays=-1
### xxl-job, access token
xxl.job.accessToken=
Loading…
Cancel
Save