Ver código fonte

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

xuxueli 7 anos atrás
pai
commit
dd94810416

+ 1 - 0
doc/XXL-JOB官方文档.md

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

+ 11 - 1
xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java

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

+ 2 - 2
xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/ScriptJobHandler.java

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

+ 18 - 2
xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobFileAppender.java

@@ -20,8 +20,21 @@ public class XxlJobFileAppender {
 	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 glueSrcPath = logBasePath.concat("/gluesource");
 	public static void initLogPath(String logPath){
 		// init
 		if (logPath!=null && logPath.trim().length()>0) {
@@ -39,11 +52,14 @@ public class XxlJobFileAppender {
 		if (!glueBaseDir.exists()) {
 			glueBaseDir.mkdirs();
 		}
+		glueSrcPath = glueBaseDir.getPath();
 	}
 	public static String getLogPath() {
 		return logBasePath;
 	}
-
+	public static String getGlueSrcPath() {
+		return glueSrcPath;
+	}
 
 	/**
 	 * log filename, like "logPath/yyyy-MM-dd/9999.log"

+ 118 - 0
xxl-job-core/src/main/java/com/xxl/job/core/thread/JobLogFileCleanThread.java

@@ -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);
+        }
+    }
+
+}

+ 27 - 0
xxl-job-core/src/main/java/com/xxl/job/core/util/FileUtil.java

@@ -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;
+    }
+
+}

+ 4 - 2
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/applicationcontext-xxl-job.xml

@@ -31,10 +31,12 @@
         <property name="appName" value="${xxl.job.executor.appname}" />
         <!-- 执行器注册中心地址[选填],为空则关闭自动注册 -->
 		<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="logPath" value="${xxl.job.executor.logpath}" />
+		<!-- 日志保存天数[选填],值大于3时生效 -->
+		<property name="logRetentionDays" value="${xxl.job.executor.logretentiondays}" />
 	</bean>
 
 

+ 5 - 2
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/xxl-job-executor.properties

@@ -6,8 +6,11 @@ xxl.job.executor.appname=xxl-job-executor-sample
 xxl.job.executor.ip=
 xxl.job.executor.port=9999
 
+### xxl-job, access token
+xxl.job.accessToken=
+
 ### xxl-job log path
 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=