Browse Source

Merge pull request #293 from liuluo129/feature/timeout

许雪里 7 years ago
parent
commit
9de5da098b
No account linked to committer's email

+ 1 - 0
doc/db/tables_xxl_job.sql View File

158
   `update_time` datetime DEFAULT NULL,
158
   `update_time` datetime DEFAULT NULL,
159
   `author` varchar(64) DEFAULT NULL COMMENT '作者',
159
   `author` varchar(64) DEFAULT NULL COMMENT '作者',
160
   `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
160
   `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
161
+  `execute_timeout` int(11) NOT NULL DEFAULT 0 COMMENT '任务执行超时时间',
161
   `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
162
   `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
162
   `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
163
   `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
163
   `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
164
   `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',

+ 11 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobInfo.java View File

36
 	// copy from quartz
36
 	// copy from quartz
37
 	private String jobStatus;		// 任务状态 【base on quartz】
37
 	private String jobStatus;		// 任务状态 【base on quartz】
38
 
38
 
39
+	private int executeTimeout;     // 任务最多执行时间,超时后报警
40
+
41
+	public int getExecuteTimeout() {
42
+		return executeTimeout;
43
+	}
44
+
45
+	public void setExecuteTimeout(int executeTimeout) {
46
+		this.executeTimeout = executeTimeout;
47
+	}
48
+
49
+
39
 	public int getId() {
50
 	public int getId() {
40
 		return id;
51
 		return id;
41
 	}
52
 	}

+ 3 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/trigger/XxlJobTrigger.java View File

96
                     triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
96
                     triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
97
                     triggerParam.setBroadcastIndex(i);
97
                     triggerParam.setBroadcastIndex(i);
98
                     triggerParam.setBroadcastTotal(addressList.size()); // update02
98
                     triggerParam.setBroadcastTotal(addressList.size()); // update02
99
+                    // 执行超时时间
100
+                    triggerParam.setExecuteTimeout(jobInfo.getExecuteTimeout());
99
 
101
 
100
                     // 4.2、trigger-run (route run / trigger remote executor)
102
                     // 4.2、trigger-run (route run / trigger remote executor)
101
                     triggerResult = runExecutor(triggerParam, address);     // update03
103
                     triggerResult = runExecutor(triggerParam, address);     // update03
164
                 triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
166
                 triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
165
                 triggerParam.setBroadcastIndex(0);
167
                 triggerParam.setBroadcastIndex(0);
166
                 triggerParam.setBroadcastTotal(1);
168
                 triggerParam.setBroadcastTotal(1);
169
+                triggerParam.setExecuteTimeout(jobInfo.getExecuteTimeout());
167
 
170
 
168
                 // 4.2、trigger-run (route run / trigger remote executor)
171
                 // 4.2、trigger-run (route run / trigger remote executor)
169
                 triggerResult = executorRouteStrategyEnum.getRouter().routeRun(triggerParam, addressList);
172
                 triggerResult = executorRouteStrategyEnum.getRouter().routeRun(triggerParam, addressList);

+ 2 - 0
xxl-job-admin/src/main/resources/i18n/message.properties View File

107
 jobinfo_field_executorparam=任务参数
107
 jobinfo_field_executorparam=任务参数
108
 jobinfo_field_cron_unvalid=Cron格式非法
108
 jobinfo_field_cron_unvalid=Cron格式非法
109
 jobinfo_field_author=负责人
109
 jobinfo_field_author=负责人
110
+jobinfo_field_timeout=最大执行时间
110
 jobinfo_field_alarmemail=报警邮件
111
 jobinfo_field_alarmemail=报警邮件
111
 jobinfo_field_alarmemail_placeholder=请输入报警邮件,多个邮件地址则逗号分隔
112
 jobinfo_field_alarmemail_placeholder=请输入报警邮件,多个邮件地址则逗号分隔
112
 jobinfo_field_executorRouteStrategy=路由策略
113
 jobinfo_field_executorRouteStrategy=路由策略
157
 joblog_clean_type_unvalid=清理类型参数异常
158
 joblog_clean_type_unvalid=清理类型参数异常
158
 joblog_handleCode_200=成功
159
 joblog_handleCode_200=成功
159
 joblog_handleCode_500=失败
160
 joblog_handleCode_500=失败
161
+joblog_handleCode_400=超时
160
 joblog_handleCode_501=失败重试
162
 joblog_handleCode_501=失败重试
161
 joblog_kill_log=终止任务
163
 joblog_kill_log=终止任务
162
 joblog_kill_log_limit=调度失败,无法终止日志
164
 joblog_kill_log_limit=调度失败,无法终止日志

+ 2 - 0
xxl-job-admin/src/main/resources/i18n/message_en.properties View File

103
 jobinfo_field_id=Job ID
103
 jobinfo_field_id=Job ID
104
 jobinfo_field_jobgroup=Executor
104
 jobinfo_field_jobgroup=Executor
105
 jobinfo_field_jobdesc=Job description
105
 jobinfo_field_jobdesc=Job description
106
+jobinfo_field_timeout=Max execute time
106
 jobinfo_field_gluetype=GLUE Type
107
 jobinfo_field_gluetype=GLUE Type
107
 jobinfo_field_executorparam=Param
108
 jobinfo_field_executorparam=Param
108
 jobinfo_field_cron_unvalid=The Cron is illegal
109
 jobinfo_field_cron_unvalid=The Cron is illegal
157
 joblog_clean_type_unvalid=Clean type is illegal
158
 joblog_clean_type_unvalid=Clean type is illegal
158
 joblog_handleCode_200=Success
159
 joblog_handleCode_200=Success
159
 joblog_handleCode_500=Fail
160
 joblog_handleCode_500=Fail
161
+joblog_handleCode_400=Timeout
160
 joblog_handleCode_501=Fail retry
162
 joblog_handleCode_501=Fail retry
161
 joblog_kill_log=Kill Job
163
 joblog_kill_log=Kill Job
162
 joblog_kill_log_limit=Trigger Fail, can not kill job
164
 joblog_kill_log_limit=Trigger Fail, can not kill job

+ 20 - 15
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml View File

1
 <?xml version="1.0" encoding="UTF-8"?>
1
 <?xml version="1.0" encoding="UTF-8"?>
2
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
2
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
3
 	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3
 	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
4
 <mapper namespace="com.xxl.job.admin.dao.XxlJobInfoDao">
4
 <mapper namespace="com.xxl.job.admin.dao.XxlJobInfoDao">
5
-	
5
+
6
 	<resultMap id="XxlJobInfo" type="com.xxl.job.admin.core.model.XxlJobInfo" >
6
 	<resultMap id="XxlJobInfo" type="com.xxl.job.admin.core.model.XxlJobInfo" >
7
 		<result column="id" property="id" />
7
 		<result column="id" property="id" />
8
-	
8
+
9
 		<result column="job_group" property="jobGroup" />
9
 		<result column="job_group" property="jobGroup" />
10
 	    <result column="job_cron" property="jobCron" />
10
 	    <result column="job_cron" property="jobCron" />
11
 	    <result column="job_desc" property="jobDesc" />
11
 	    <result column="job_desc" property="jobDesc" />
12
-	    
12
+
13
 	    <result column="add_time" property="addTime" />
13
 	    <result column="add_time" property="addTime" />
14
 	    <result column="update_time" property="updateTime" />
14
 	    <result column="update_time" property="updateTime" />
15
-	    
15
+
16
 	    <result column="author" property="author" />
16
 	    <result column="author" property="author" />
17
 	    <result column="alarm_email" property="alarmEmail" />
17
 	    <result column="alarm_email" property="alarmEmail" />
18
 
18
 
21
 	    <result column="executor_param" property="executorParam" />
21
 	    <result column="executor_param" property="executorParam" />
22
 		<result column="executor_block_strategy" property="executorBlockStrategy" />
22
 		<result column="executor_block_strategy" property="executorBlockStrategy" />
23
 		<result column="executor_fail_strategy" property="executorFailStrategy" />
23
 		<result column="executor_fail_strategy" property="executorFailStrategy" />
24
-	    
24
+
25
 	    <result column="glue_type" property="glueType" />
25
 	    <result column="glue_type" property="glueType" />
26
 	    <result column="glue_source" property="glueSource" />
26
 	    <result column="glue_source" property="glueSource" />
27
 	    <result column="glue_remark" property="glueRemark" />
27
 	    <result column="glue_remark" property="glueRemark" />
28
 		<result column="glue_updatetime" property="glueUpdatetime" />
28
 		<result column="glue_updatetime" property="glueUpdatetime" />
29
+		<result column="execute_timeout" property="executeTimeout" />
29
 
30
 
30
 		<result column="child_jobid" property="childJobId" />
31
 		<result column="child_jobid" property="childJobId" />
31
 	</resultMap>
32
 	</resultMap>
48
 		t.glue_source,
49
 		t.glue_source,
49
 		t.glue_remark,
50
 		t.glue_remark,
50
 		t.glue_updatetime,
51
 		t.glue_updatetime,
52
+		t.execute_timeout,
51
 		t.child_jobid
53
 		t.child_jobid
52
 	</sql>
54
 	</sql>
53
-	
55
+
54
 	<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
56
 	<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
55
 		SELECT <include refid="Base_Column_List" />
57
 		SELECT <include refid="Base_Column_List" />
56
 		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
58
 		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
68
 		ORDER BY id DESC
70
 		ORDER BY id DESC
69
 		LIMIT #{offset}, #{pagesize}
71
 		LIMIT #{offset}, #{pagesize}
70
 	</select>
72
 	</select>
71
-	
73
+
72
 	<select id="pageListCount" parameterType="java.util.HashMap" resultType="int">
74
 	<select id="pageListCount" parameterType="java.util.HashMap" resultType="int">
73
 		SELECT count(1)
75
 		SELECT count(1)
74
 		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
76
 		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
103
 			glue_source,
105
 			glue_source,
104
 			glue_remark,
106
 			glue_remark,
105
 			glue_updatetime,
107
 			glue_updatetime,
106
-			child_jobid
108
+			child_jobid,
109
+		    execute_timeout
107
 		) VALUES (
110
 		) VALUES (
108
 			#{jobGroup},
111
 			#{jobGroup},
109
-			#{jobCron}, 
112
+			#{jobCron},
110
 			#{jobDesc},
113
 			#{jobDesc},
111
 			NOW(),
114
 			NOW(),
112
 			NOW(),
115
 			NOW(),
121
 			#{glueSource},
124
 			#{glueSource},
122
 			#{glueRemark},
125
 			#{glueRemark},
123
 			NOW(),
126
 			NOW(),
124
-			#{childJobId}
127
+			#{childJobId},
128
+		    #{executeTimeout}
125
 		);
129
 		);
126
 		<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
130
 		<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
127
 			SELECT LAST_INSERT_ID()
131
 			SELECT LAST_INSERT_ID()
134
 		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
138
 		FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
135
 		WHERE t.id = #{id}
139
 		WHERE t.id = #{id}
136
 	</select>
140
 	</select>
137
-	
141
+
138
 	<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" >
142
 	<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" >
139
 		UPDATE XXL_JOB_QRTZ_TRIGGER_INFO
143
 		UPDATE XXL_JOB_QRTZ_TRIGGER_INFO
140
-		SET 
144
+		SET
141
 			job_cron = #{jobCron},
145
 			job_cron = #{jobCron},
142
 			job_desc = #{jobDesc},
146
 			job_desc = #{jobDesc},
143
 			update_time = NOW(),
147
 			update_time = NOW(),
152
 			glue_source = #{glueSource},
156
 			glue_source = #{glueSource},
153
 			glue_remark = #{glueRemark},
157
 			glue_remark = #{glueRemark},
154
 			glue_updatetime = #{glueUpdatetime},
158
 			glue_updatetime = #{glueUpdatetime},
155
-			child_jobid = #{childJobId}
159
+			child_jobid = #{childJobId},
160
+			execute_timeout = ${executeTimeout}
156
 		WHERE id = #{id}
161
 		WHERE id = #{id}
157
 	</update>
162
 	</update>
158
-	
163
+
159
 	<delete id="delete" parameterType="java.util.HashMap">
164
 	<delete id="delete" parameterType="java.util.HashMap">
160
 		DELETE
165
 		DELETE
161
 		FROM XXL_JOB_QRTZ_TRIGGER_INFO
166
 		FROM XXL_JOB_QRTZ_TRIGGER_INFO

+ 5 - 0
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl View File

169
 						<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="${I18n.jobinfo_field_alarmemail_placeholder}" maxlength="100" ></div>
169
 						<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="${I18n.jobinfo_field_alarmemail_placeholder}" maxlength="100" ></div>
170
 					</div>
170
 					</div>
171
 
171
 
172
+					<div class="form-group">
173
+						<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_timeout}<font color="red">*</font></label>
174
+						<div class="col-sm-4"><input type="text" class="form-control" name="executeTimeout" placeholder="0" maxlength="100" ></div>
175
+					</div>
176
+
172
                     <hr>
177
                     <hr>
173
 					<div class="form-group">
178
 					<div class="form-group">
174
 						<div class="col-sm-offset-3 col-sm-6">
179
 						<div class="col-sm-offset-3 col-sm-6">

+ 1 - 0
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js View File

362
 		$("#updateModal .form input[name='jobCron']").val( row.jobCron );
362
 		$("#updateModal .form input[name='jobCron']").val( row.jobCron );
363
 		$("#updateModal .form input[name='author']").val( row.author );
363
 		$("#updateModal .form input[name='author']").val( row.author );
364
 		$("#updateModal .form input[name='alarmEmail']").val( row.alarmEmail );
364
 		$("#updateModal .form input[name='alarmEmail']").val( row.alarmEmail );
365
+		$("#updateModal .form input[name='executeTimeout']").val( row.executeTimeout );
365
 		$('#updateModal .form select[name=executorRouteStrategy] option[value='+ row.executorRouteStrategy +']').prop('selected', true);
366
 		$('#updateModal .form select[name=executorRouteStrategy] option[value='+ row.executorRouteStrategy +']').prop('selected', true);
366
 		$("#updateModal .form input[name='executorHandler']").val( row.executorHandler );
367
 		$("#updateModal .form input[name='executorHandler']").val( row.executorHandler );
367
 		$("#updateModal .form input[name='executorParam']").val( row.executorParam );
368
 		$("#updateModal .form input[name='executorParam']").val( row.executorParam );

+ 2 - 0
xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js View File

159
                                 html = '<span style="color: red">'+ I18n.joblog_handleCode_500 +'</span>';
159
                                 html = '<span style="color: red">'+ I18n.joblog_handleCode_500 +'</span>';
160
                             } else if (data == 501) {
160
                             } else if (data == 501) {
161
                                 html = '<span style="color: red">'+ I18n.joblog_handleCode_501 +'</span>';
161
                                 html = '<span style="color: red">'+ I18n.joblog_handleCode_501 +'</span>';
162
+                            } else if (data == 400) {
163
+                                html = '<span style="color: red">'+ I18n.joblog_handleCode_400 +'</span>';
162
                             } else if (data == 0) {
164
                             } else if (data == 0) {
163
                                 html = '';
165
                                 html = '';
164
                             }
166
                             }

+ 3 - 0
xxl-job-core/src/main/java/com/xxl/job/core/biz/model/ReturnT.java View File

12
 
12
 
13
 	public static final int SUCCESS_CODE = 200;
13
 	public static final int SUCCESS_CODE = 200;
14
 	public static final int FAIL_CODE = 500;
14
 	public static final int FAIL_CODE = 500;
15
+	public static final int EXECUTE_TIMEOUT = 400;
16
+
15
 	public static final ReturnT<String> SUCCESS = new ReturnT<String>(null);
17
 	public static final ReturnT<String> SUCCESS = new ReturnT<String>(null);
16
 	public static final ReturnT<String> FAIL = new ReturnT<String>(FAIL_CODE, null);
18
 	public static final ReturnT<String> FAIL = new ReturnT<String>(FAIL_CODE, null);
19
+	public static final ReturnT<String> TIMEOUT = new ReturnT<String>(EXECUTE_TIMEOUT, "执行超时");
17
 	
20
 	
18
 	private int code;
21
 	private int code;
19
 	private String msg;
22
 	private String msg;

+ 10 - 0
xxl-job-core/src/main/java/com/xxl/job/core/biz/model/TriggerParam.java View File

24
     private int broadcastIndex;
24
     private int broadcastIndex;
25
     private int broadcastTotal;
25
     private int broadcastTotal;
26
 
26
 
27
+    private int executeTimeout;
28
+
29
+    public int getExecuteTimeout() {
30
+        return executeTimeout;
31
+    }
32
+
33
+    public void setExecuteTimeout(int executeTimeout) {
34
+        this.executeTimeout = executeTimeout;
35
+    }
36
+
27
     public int getJobId() {
37
     public int getJobId() {
28
         return jobId;
38
         return jobId;
29
     }
39
     }

+ 2 - 0
xxl-job-core/src/main/java/com/xxl/job/core/handler/IJobHandler.java View File

14
 	public static final ReturnT<String> SUCCESS = new ReturnT<String>(200, null);
14
 	public static final ReturnT<String> SUCCESS = new ReturnT<String>(200, null);
15
 	/** fail */
15
 	/** fail */
16
 	public static final ReturnT<String> FAIL = new ReturnT<String>(500, null);
16
 	public static final ReturnT<String> FAIL = new ReturnT<String>(500, null);
17
+	/** timeout */
18
+	public static final ReturnT<String> TIMEOUT = new ReturnT<String>(400, null);
17
 	/** fail retry */
19
 	/** fail retry */
18
 	public static final ReturnT<String> FAIL_RETRY = new ReturnT<String>(501, null);
20
 	public static final ReturnT<String> FAIL_RETRY = new ReturnT<String>(501, null);
19
 
21
 

+ 29 - 1
xxl-job-core/src/main/java/com/xxl/job/core/thread/JobThread.java View File

15
 import java.io.StringWriter;
15
 import java.io.StringWriter;
16
 import java.util.Collections;
16
 import java.util.Collections;
17
 import java.util.Date;
17
 import java.util.Date;
18
+
19
+import java.util.concurrent.*;
20
+
18
 import java.util.HashSet;
21
 import java.util.HashSet;
19
 import java.util.Set;
22
 import java.util.Set;
20
 import java.util.concurrent.LinkedBlockingQueue;
23
 import java.util.concurrent.LinkedBlockingQueue;
21
 import java.util.concurrent.TimeUnit;
24
 import java.util.concurrent.TimeUnit;
22
 
25
 
26
+
23
 /**
27
 /**
24
  * handler thread
28
  * handler thread
25
  * @author xuxueli 2016-1-16 19:52:47
29
  * @author xuxueli 2016-1-16 19:52:47
107
 
111
 
108
             TriggerParam triggerParam = null;
112
             TriggerParam triggerParam = null;
109
             ReturnT<String> executeResult = null;
113
             ReturnT<String> executeResult = null;
114
+			ExecutorService singleThread = Executors.newSingleThreadExecutor();
110
             try {
115
             try {
111
 				// to check toStop signal, we need cycle, so wo cannot use queue.take(), instand of poll(timeout)
116
 				// to check toStop signal, we need cycle, so wo cannot use queue.take(), instand of poll(timeout)
112
 				triggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS);
117
 				triggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS);
122
 
127
 
123
 					// execute
128
 					// execute
124
 					XxlJobLogger.log("<br>----------- xxl-job job execute start -----------<br>----------- Param:" + triggerParam.getExecutorParams());
129
 					XxlJobLogger.log("<br>----------- xxl-job job execute start -----------<br>----------- Param:" + triggerParam.getExecutorParams());
125
-					executeResult = handler.execute(triggerParam.getExecutorParams());
130
+					int executeTimeout = triggerParam.getExecuteTimeout();
131
+
132
+
133
+					final TriggerParam finalTriggerParam = triggerParam;
134
+
135
+					Future<ReturnT<String>> future = singleThread.submit(new Callable<ReturnT<String>>() {
136
+						@Override
137
+						public ReturnT<String> call() throws Exception {
138
+							return handler.execute(finalTriggerParam.getExecutorParams());
139
+						}
140
+					});
141
+
142
+					try {
143
+						if (executeTimeout > 0) {
144
+							executeResult = future.get(executeTimeout, TimeUnit.SECONDS);
145
+						} else {
146
+							executeResult = future.get();
147
+						}
148
+					} catch (TimeoutException timeoutException) {
149
+						executeResult = ReturnT.TIMEOUT;
150
+					}
126
 					if (executeResult == null) {
151
 					if (executeResult == null) {
127
 						executeResult = IJobHandler.FAIL;
152
 						executeResult = IJobHandler.FAIL;
128
 					}
153
 					}
145
 
170
 
146
 				XxlJobLogger.log("<br>----------- JobThread Exception:" + errorMsg + "<br>----------- xxl-job job execute end(error) -----------");
171
 				XxlJobLogger.log("<br>----------- JobThread Exception:" + errorMsg + "<br>----------- xxl-job job execute end(error) -----------");
147
 			} finally {
172
 			} finally {
173
+            	if (singleThread != null) {
174
+            		singleThread.shutdown();
175
+				}
148
                 if(triggerParam != null) {
176
                 if(triggerParam != null) {
149
                     // callback handler info
177
                     // callback handler info
150
                     if (!toStop) {
178
                     if (!toStop) {