浏览代码

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

xuxueli 8 年前
父节点
当前提交
dd94810416

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

@@ -1112,6 +1112,7 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
1112 1112
 - 28、新增"任务ID"属性,移除"JobKey"属性,前者承担所有功能,方便后续增强任务依赖功能。
1113 1113
 - 29、任务循环依赖问题修复,避免子任务与父任务重复导致的调度死循环;
1114 1114
 - 30、任务列表新增筛选条件 "任务描述",快速检索任务;
1115
+- 31、执行器新增配置项("xxl.job.executor.logretentiondays"):日志保存天数,执行器自动删除过期日志文件。限制配置最少保存3天,否则功能无效。
1115 1116
 
1116 1117
 ### TODO LIST
1117 1118
 - 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;
8 8
 import com.xxl.job.core.log.XxlJobFileAppender;
9 9
 import com.xxl.job.core.rpc.netcom.NetComClientProxy;
10 10
 import com.xxl.job.core.rpc.netcom.NetComServerFactory;
11
+import com.xxl.job.core.thread.JobLogFileCleanThread;
11 12
 import com.xxl.job.core.thread.JobThread;
12 13
 import com.xxl.job.core.util.NetUtil;
13 14
 import org.slf4j.Logger;
@@ -34,6 +35,7 @@ public class XxlJobExecutor implements ApplicationContextAware {
34 35
     private String adminAddresses;
35 36
     private String accessToken;
36 37
     private String logPath;
38
+    private int logRetentionDays;
37 39
 
38 40
     public void setIp(String ip) {
39 41
         this.ip = ip;
@@ -53,7 +55,9 @@ public class XxlJobExecutor implements ApplicationContextAware {
53 55
     public void setLogPath(String logPath) {
54 56
         this.logPath = logPath;
55 57
     }
56
-
58
+    public void setLogRetentionDays(int logRetentionDays) {
59
+        this.logRetentionDays = logRetentionDays;
60
+    }
57 61
 
58 62
     // ---------------------- applicationContext ----------------------
59 63
     private static ApplicationContext applicationContext;
@@ -79,6 +83,9 @@ public class XxlJobExecutor implements ApplicationContextAware {
79 83
 
80 84
         // init executor-server
81 85
         initExecutorServer(port, ip, appName, accessToken);
86
+
87
+        // init JobLogFileCleanThread
88
+        JobLogFileCleanThread.getInstance().start(logRetentionDays);
82 89
     }
83 90
     public void destroy(){
84 91
         // destory JobThreadRepository
@@ -91,6 +98,9 @@ public class XxlJobExecutor implements ApplicationContextAware {
91 98
 
92 99
         // destory executor-server
93 100
         stopExecutorServer();
101
+
102
+        // destory JobLogFileCleanThread
103
+        JobLogFileCleanThread.getInstance().toStop();
94 104
     }
95 105
 
96 106
 

+ 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 {
40 40
         String cmd = glueType.getCmd();
41 41
 
42 42
         // make script file
43
-        String scriptFileName = XxlJobFileAppender.getLogPath()
44
-                .concat("/gluesource/")
43
+        String scriptFileName = XxlJobFileAppender.getGlueSrcPath()
44
+                .concat("/")
45 45
                 .concat(String.valueOf(jobId))
46 46
                 .concat("_")
47 47
                 .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 {
20 20
 	public static final InheritableThreadLocal<String> contextHolder = new InheritableThreadLocal<String>();
21 21
 
22 22
 
23
-	// log base path
23
+	/**
24
+	 * log base path
25
+	 *
26
+	 * strut like:
27
+	 * 	---/
28
+	 * 	---/gluesource/
29
+	 * 	---/gluesource/10_1514171108000.js
30
+	 * 	---/gluesource/10_1514171108000.js
31
+	 * 	---/2017-12-25/
32
+	 * 	---/2017-12-25/639.log
33
+	 * 	---/2017-12-25/821.log
34
+	 *
35
+	 */
24 36
 	private static String logBasePath = "/data/applogs/xxl-job/jobhandler";
37
+	private static String glueSrcPath = logBasePath.concat("/gluesource");
25 38
 	public static void initLogPath(String logPath){
26 39
 		// init
27 40
 		if (logPath!=null && logPath.trim().length()>0) {
@@ -39,11 +52,14 @@ public class XxlJobFileAppender {
39 52
 		if (!glueBaseDir.exists()) {
40 53
 			glueBaseDir.mkdirs();
41 54
 		}
55
+		glueSrcPath = glueBaseDir.getPath();
42 56
 	}
43 57
 	public static String getLogPath() {
44 58
 		return logBasePath;
45 59
 	}
46
-
60
+	public static String getGlueSrcPath() {
61
+		return glueSrcPath;
62
+	}
47 63
 
48 64
 	/**
49 65
 	 * 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 @@
1
+package com.xxl.job.core.thread;
2
+
3
+import com.xxl.job.core.log.XxlJobFileAppender;
4
+import com.xxl.job.core.util.FileUtil;
5
+import org.slf4j.Logger;
6
+import org.slf4j.LoggerFactory;
7
+
8
+import java.io.File;
9
+import java.text.ParseException;
10
+import java.text.SimpleDateFormat;
11
+import java.util.Calendar;
12
+import java.util.Date;
13
+import java.util.concurrent.TimeUnit;
14
+
15
+/**
16
+ * job file clean thread
17
+ *
18
+ * @author xuxueli 2017-12-29 16:23:43
19
+ */
20
+public class JobLogFileCleanThread extends Thread {
21
+    private static Logger logger = LoggerFactory.getLogger(JobLogFileCleanThread.class);
22
+
23
+    private static JobLogFileCleanThread instance = new JobLogFileCleanThread();
24
+    public static JobLogFileCleanThread getInstance(){
25
+        return instance;
26
+    }
27
+
28
+    private Thread localThread;
29
+    private volatile boolean toStop = false;
30
+    public void start(final long logRetentionDays){
31
+
32
+        // limit min value
33
+        if (logRetentionDays < 3 ) {
34
+            return;
35
+        }
36
+
37
+        localThread = new Thread(new Runnable() {
38
+            @Override
39
+            public void run() {
40
+                while (!toStop) {
41
+                    try {
42
+                        // clean log dir, over logRetentionDays
43
+                        File[] childDirs = new File(XxlJobFileAppender.getLogPath()).listFiles();
44
+                        if (childDirs!=null && childDirs.length>0) {
45
+
46
+                            // today
47
+                            Calendar todayCal = Calendar.getInstance();
48
+                            todayCal.set(Calendar.HOUR_OF_DAY,0);
49
+                            todayCal.set(Calendar.MINUTE,0);
50
+                            todayCal.set(Calendar.SECOND,0);
51
+                            todayCal.set(Calendar.MILLISECOND,0);
52
+
53
+                            Date todayDate = todayCal.getTime();
54
+
55
+                            for (File childFile: childDirs) {
56
+
57
+                                // valid
58
+                                if (!childFile.isDirectory()) {
59
+                                    continue;
60
+                                }
61
+                                if (childFile.getName().indexOf("-") == -1) {
62
+                                    continue;
63
+                                }
64
+
65
+                                // file create date
66
+                                Date logFileCreateDate = null;
67
+                                try {
68
+                                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
69
+                                    logFileCreateDate = simpleDateFormat.parse(childFile.getName());
70
+                                } catch (ParseException e) {
71
+                                    logger.error(e.getMessage(), e);
72
+                                }
73
+                                if (logFileCreateDate == null) {
74
+                                    continue;
75
+                                }
76
+
77
+                                if ((todayDate.getTime()-logFileCreateDate.getTime()) >= logRetentionDays * (24 * 60 * 60 * 1000) ) {
78
+                                    FileUtil.deleteRecursively(childFile);
79
+                                }
80
+
81
+                            }
82
+                        }
83
+
84
+                    } catch (Exception e) {
85
+                        logger.error(e.getMessage(), e);
86
+                    }
87
+
88
+                    try {
89
+                        TimeUnit.DAYS.sleep(1);
90
+                    } catch (InterruptedException e) {
91
+                        logger.error(e.getMessage(), e);
92
+                    }
93
+                }
94
+                logger.info(">>>>>>>>>>> xxl-job, executor JobLogFileCleanThread thread destory.");
95
+
96
+            }
97
+        });
98
+        localThread.setDaemon(true);
99
+        localThread.start();
100
+    }
101
+
102
+    public void toStop() {
103
+        toStop = true;
104
+
105
+        if (localThread == null) {
106
+            return;
107
+        }
108
+
109
+        // interrupt and wait
110
+        localThread.interrupt();
111
+        try {
112
+            localThread.join();
113
+        } catch (InterruptedException e) {
114
+            logger.error(e.getMessage(), e);
115
+        }
116
+    }
117
+
118
+}

+ 27 - 0
xxl-job-core/src/main/java/com/xxl/job/core/util/FileUtil.java 查看文件

@@ -0,0 +1,27 @@
1
+package com.xxl.job.core.util;
2
+
3
+import java.io.File;
4
+
5
+/**
6
+ * file tool
7
+ *
8
+ * @author xuxueli 2017-12-29 17:56:48
9
+ */
10
+public class FileUtil {
11
+
12
+    public static boolean deleteRecursively(File root) {
13
+        if (root != null && root.exists()) {
14
+            if (root.isDirectory()) {
15
+                File[] children = root.listFiles();
16
+                if (children != null) {
17
+                    for (File child : children) {
18
+                        deleteRecursively(child);
19
+                    }
20
+                }
21
+            }
22
+            return root.delete();
23
+        }
24
+        return false;
25
+    }
26
+
27
+}

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

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

+ 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
6 6
 xxl.job.executor.ip=
7 7
 xxl.job.executor.port=9999
8 8
 
9
+### xxl-job, access token
10
+xxl.job.accessToken=
11
+
9 12
 ### xxl-job log path
10 13
 xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
14
+### xxl-job log retention days
15
+xxl.job.executor.logretentiondays=-1
11 16
 
12
-### xxl-job, access token
13
-xxl.job.accessToken=