Browse Source

阻塞处理策略

xueli.xue 8 years ago
parent
commit
744c00494b

+ 1 - 1
xxl-job-admin/src/main/java/com/xxl/job/admin/core/biz/AdminBizImpl.java View File

69
             handleMsg.append(log.getHandleMsg()).append("<br>");
69
             handleMsg.append(log.getHandleMsg()).append("<br>");
70
         }
70
         }
71
         if (handleCallbackParam.getExecuteResult().getMsg() != null) {
71
         if (handleCallbackParam.getExecuteResult().getMsg() != null) {
72
-            handleMsg.append("执行备注:").append(handleCallbackParam.getExecuteResult().getMsg());
72
+            handleMsg.append(handleCallbackParam.getExecuteResult().getMsg());
73
         }
73
         }
74
         if (childTriggerMsg !=null) {
74
         if (childTriggerMsg !=null) {
75
             handleMsg.append("<br>子任务触发备注:").append(childTriggerMsg);
75
             handleMsg.append("<br>子任务触发备注:").append(childTriggerMsg);

+ 59 - 41
xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java View File

33
     public ReturnT<String> kill(int jobId) {
33
     public ReturnT<String> kill(int jobId) {
34
         // kill handlerThread, and create new one
34
         // kill handlerThread, and create new one
35
         JobThread jobThread = XxlJobExecutor.loadJobThread(jobId);
35
         JobThread jobThread = XxlJobExecutor.loadJobThread(jobId);
36
-
37
         if (jobThread != null) {
36
         if (jobThread != null) {
38
-            IJobHandler handler = jobThread.getHandler();
39
-            jobThread.toStop("人工手动终止");
40
-            jobThread.interrupt();
41
-            XxlJobExecutor.removeJobThread(jobId);
37
+            XxlJobExecutor.removeJobThread(jobId, "人工手动终止");
42
             return ReturnT.SUCCESS;
38
             return ReturnT.SUCCESS;
43
         }
39
         }
44
 
40
 
56
 
52
 
57
     @Override
53
     @Override
58
     public ReturnT<String> run(TriggerParam triggerParam) {
54
     public ReturnT<String> run(TriggerParam triggerParam) {
59
-        // load old thread
55
+        // load old:jobHandler + jobThread
60
         JobThread jobThread = XxlJobExecutor.loadJobThread(triggerParam.getJobId());
56
         JobThread jobThread = XxlJobExecutor.loadJobThread(triggerParam.getJobId());
57
+        IJobHandler jobHandler = jobThread!=null?jobThread.getHandler():null;
58
+        String removeOldReason = null;
61
 
59
 
60
+        // valid:jobHandler + jobThread
62
         if (GlueTypeEnum.BEAN==GlueTypeEnum.match(triggerParam.getGlueType())) {
61
         if (GlueTypeEnum.BEAN==GlueTypeEnum.match(triggerParam.getGlueType())) {
63
 
62
 
64
-            // valid handler
65
-            IJobHandler jobHandler = XxlJobExecutor.loadJobHandler(triggerParam.getExecutorHandler());
66
-            if (jobHandler==null) {
67
-                return new ReturnT<String>(ReturnT.FAIL_CODE, "job handler [" + triggerParam.getExecutorHandler() + "] not found.");
68
-            }
63
+            // valid old jobThread
64
+            if (jobThread != null && jobHandler!=null && jobThread.getHandler() != jobHandler) {
65
+                // change handler, need kill old thread
66
+                removeOldReason = "更新JobHandler或更换任务模式,终止旧任务线程";
69
 
67
 
70
-            // valid exists job thread:change handler, need kill old thread
71
-            if (jobThread != null && jobThread.getHandler() != jobHandler) {
72
-                // kill old job thread
73
-                jobThread.toStop("更换任务模式或JobHandler,终止旧任务线程");
74
-                jobThread.interrupt();
75
-                XxlJobExecutor.removeJobThread(triggerParam.getJobId());
76
                 jobThread = null;
68
                 jobThread = null;
69
+                jobHandler = null;
77
             }
70
             }
78
 
71
 
79
-            // make thread: new or exists invalid
80
-            if (jobThread == null) {
81
-                jobThread = XxlJobExecutor.registJobThread(triggerParam.getJobId(), jobHandler);
72
+            // valid handler
73
+            if (jobHandler == null) {
74
+                jobHandler = XxlJobExecutor.loadJobHandler(triggerParam.getExecutorHandler());
75
+                if (jobHandler == null) {
76
+                    return new ReturnT<String>(ReturnT.FAIL_CODE, "job handler [" + triggerParam.getExecutorHandler() + "] not found.");
77
+                }
82
             }
78
             }
83
 
79
 
84
         } else if (GlueTypeEnum.GLUE_GROOVY==GlueTypeEnum.match(triggerParam.getGlueType())) {
80
         } else if (GlueTypeEnum.GLUE_GROOVY==GlueTypeEnum.match(triggerParam.getGlueType())) {
85
 
81
 
86
-            // valid exists job thread:change handler or gluesource updated, need kill old thread
82
+            // valid old jobThread
87
             if (jobThread != null &&
83
             if (jobThread != null &&
88
                     !(jobThread.getHandler() instanceof GlueJobHandler
84
                     !(jobThread.getHandler() instanceof GlueJobHandler
89
                         && ((GlueJobHandler) jobThread.getHandler()).getGlueUpdatetime()==triggerParam.getGlueUpdatetime() )) {
85
                         && ((GlueJobHandler) jobThread.getHandler()).getGlueUpdatetime()==triggerParam.getGlueUpdatetime() )) {
90
-                // change glue model or gluesource updated, kill old job thread
91
-                jobThread.toStop("更换任务模式或JobHandler,终止旧任务线程");
92
-                jobThread.interrupt();
93
-                XxlJobExecutor.removeJobThread(triggerParam.getJobId());
86
+                // change handler or gluesource updated, need kill old thread
87
+                removeOldReason = "更新任务逻辑或更换任务模式,终止旧任务线程";
88
+
94
                 jobThread = null;
89
                 jobThread = null;
90
+                jobHandler = null;
95
             }
91
             }
96
 
92
 
97
-            // make thread: new or exists invalid
98
-            if (jobThread == null) {
99
-                IJobHandler jobHandler = null;
93
+            // valid handler
94
+            if (jobHandler == null) {
100
                 try {
95
                 try {
101
-                    jobHandler = GlueFactory.getInstance().loadNewInstance(triggerParam.getGlueSource());
96
+                    IJobHandler originJobHandler = GlueFactory.getInstance().loadNewInstance(triggerParam.getGlueSource());
97
+                    jobHandler = new GlueJobHandler(originJobHandler, triggerParam.getGlueUpdatetime());
102
                 } catch (Exception e) {
98
                 } catch (Exception e) {
103
                     logger.error("", e);
99
                     logger.error("", e);
104
                     return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());
100
                     return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());
105
                 }
101
                 }
106
-                jobThread = XxlJobExecutor.registJobThread(triggerParam.getJobId(), new GlueJobHandler(jobHandler, triggerParam.getGlueUpdatetime()));
107
             }
102
             }
108
         } else if (GlueTypeEnum.GLUE_SHELL==GlueTypeEnum.match(triggerParam.getGlueType())
103
         } else if (GlueTypeEnum.GLUE_SHELL==GlueTypeEnum.match(triggerParam.getGlueType())
109
                 || GlueTypeEnum.GLUE_PYTHON==GlueTypeEnum.match(triggerParam.getGlueType()) ) {
104
                 || GlueTypeEnum.GLUE_PYTHON==GlueTypeEnum.match(triggerParam.getGlueType()) ) {
110
 
105
 
111
-            // valid exists job thread:change script or gluesource updated, need kill old thread
106
+            // valid old jobThread
112
             if (jobThread != null &&
107
             if (jobThread != null &&
113
                     !(jobThread.getHandler() instanceof ScriptJobHandler
108
                     !(jobThread.getHandler() instanceof ScriptJobHandler
114
                             && ((ScriptJobHandler) jobThread.getHandler()).getGlueUpdatetime()==triggerParam.getGlueUpdatetime() )) {
109
                             && ((ScriptJobHandler) jobThread.getHandler()).getGlueUpdatetime()==triggerParam.getGlueUpdatetime() )) {
115
-                // change glue model or gluesource updated, kill old job thread
116
-                jobThread.toStop("更换任务模式或JobHandler,终止旧任务线程");
117
-                jobThread.interrupt();
118
-                XxlJobExecutor.removeJobThread(triggerParam.getJobId());
110
+                // change script or gluesource updated, need kill old thread
111
+                removeOldReason = "更新任务逻辑或更换任务模式,终止旧任务线程";
112
+
119
                 jobThread = null;
113
                 jobThread = null;
114
+                jobHandler = null;
120
             }
115
             }
121
 
116
 
122
-            // make thread: new or exists invalid
123
-            if (jobThread == null) {
124
-                ScriptJobHandler scriptJobHandler = new ScriptJobHandler(triggerParam.getJobId(), triggerParam.getGlueUpdatetime(), triggerParam.getGlueSource(), GlueTypeEnum.match(triggerParam.getGlueType()));
125
-                jobThread = XxlJobExecutor.registJobThread(triggerParam.getJobId(), scriptJobHandler);
117
+            // valid handler
118
+            if (jobHandler == null) {
119
+                jobHandler = new ScriptJobHandler(triggerParam.getJobId(), triggerParam.getGlueUpdatetime(), triggerParam.getGlueSource(), GlueTypeEnum.match(triggerParam.getGlueType()));
126
             }
120
             }
127
         } else {
121
         } else {
128
             return new ReturnT<String>(ReturnT.FAIL_CODE, "glueType[" + triggerParam.getGlueType() + "] is not valid.");
122
             return new ReturnT<String>(ReturnT.FAIL_CODE, "glueType[" + triggerParam.getGlueType() + "] is not valid.");
129
         }
123
         }
130
 
124
 
125
+        // executor block strategy
126
+        if (jobThread != null) {
127
+            ExecutorBlockStrategyEnum blockStrategy = ExecutorBlockStrategyEnum.match(triggerParam.getExecutorBlockStrategy(), null);
128
+            if (ExecutorBlockStrategyEnum.DISCARD_LATER == blockStrategy) {
129
+                // discard when running
130
+                if (jobThread.isRunningOrHasQueue()) {
131
+                    return new ReturnT<String>(ReturnT.FAIL_CODE, "阻塞处理策略-生效:"+ExecutorBlockStrategyEnum.DISCARD_LATER.getTitle());
132
+                }
133
+            } else if (ExecutorBlockStrategyEnum.COVER_EARLY == blockStrategy) {
134
+                // kill running jobThread
135
+                if (jobThread.isRunningOrHasQueue()) {
136
+                    removeOldReason = "阻塞处理策略-生效:" + ExecutorBlockStrategyEnum.COVER_EARLY.getTitle();
137
+
138
+                    jobThread = null;
139
+                }
140
+            } else {
141
+                // just queue trigger
142
+            }
143
+        }
144
+
145
+        // replace thread (new or exists invalid)
146
+        if (jobThread == null) {
147
+            jobThread = XxlJobExecutor.registJobThread(triggerParam.getJobId(), jobHandler, removeOldReason);
148
+        }
149
+
131
         // push data to queue
150
         // push data to queue
132
-        ExecutorBlockStrategyEnum blockStrategy = ExecutorBlockStrategyEnum.match(triggerParam.getExecutorBlockStrategy(), null);
133
-        ReturnT<String> pushResult = jobThread.pushTriggerQueue(triggerParam, blockStrategy);
151
+        ReturnT<String> pushResult = jobThread.pushTriggerQueue(triggerParam);
134
         return pushResult;
152
         return pushResult;
135
     }
153
     }
136
 
154
 

+ 18 - 8
xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java View File

121
 
121
 
122
     // ---------------------------------- job thread repository
122
     // ---------------------------------- job thread repository
123
     private static ConcurrentHashMap<Integer, JobThread> JobThreadRepository = new ConcurrentHashMap<Integer, JobThread>();
123
     private static ConcurrentHashMap<Integer, JobThread> JobThreadRepository = new ConcurrentHashMap<Integer, JobThread>();
124
-    public static JobThread registJobThread(int jobId, IJobHandler handler){
125
-        JobThread jobThread = new JobThread(handler);
126
-        jobThread.start();
124
+    public static JobThread registJobThread(int jobId, IJobHandler handler, String removeOldReason){
125
+        JobThread newJobThread = new JobThread(handler);
126
+        newJobThread.start();
127
         logger.info(">>>>>>>>>>> xxl-job regist JobThread success, jobId:{}, handler:{}", new Object[]{jobId, handler});
127
         logger.info(">>>>>>>>>>> xxl-job regist JobThread success, jobId:{}, handler:{}", new Object[]{jobId, handler});
128
-        JobThreadRepository.put(jobId, jobThread);	// putIfAbsent | oh my god, map's put method return the old value!!!
129
-        return jobThread;
128
+
129
+        JobThread oldJobThread = JobThreadRepository.put(jobId, newJobThread);	// putIfAbsent | oh my god, map's put method return the old value!!!
130
+        if (oldJobThread != null) {
131
+            oldJobThread.toStop(removeOldReason);
132
+            oldJobThread.interrupt();
133
+        }
134
+
135
+        return newJobThread;
136
+    }
137
+    public static void removeJobThread(int jobId, String removeOldReason){
138
+        JobThread oldJobThread = JobThreadRepository.remove(jobId);
139
+        if (oldJobThread != null) {
140
+            oldJobThread.toStop(removeOldReason);
141
+            oldJobThread.interrupt();
142
+        }
130
     }
143
     }
131
     public static JobThread loadJobThread(int jobId){
144
     public static JobThread loadJobThread(int jobId){
132
         JobThread jobThread = JobThreadRepository.get(jobId);
145
         JobThread jobThread = JobThreadRepository.get(jobId);
133
         return jobThread;
146
         return jobThread;
134
     }
147
     }
135
-    public static void removeJobThread(int jobId){
136
-        JobThreadRepository.remove(jobId);
137
-    }
138
 
148
 
139
 }
149
 }

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

3
 import com.xxl.job.core.biz.model.HandleCallbackParam;
3
 import com.xxl.job.core.biz.model.HandleCallbackParam;
4
 import com.xxl.job.core.biz.model.ReturnT;
4
 import com.xxl.job.core.biz.model.ReturnT;
5
 import com.xxl.job.core.biz.model.TriggerParam;
5
 import com.xxl.job.core.biz.model.TriggerParam;
6
-import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
7
 import com.xxl.job.core.handler.IJobHandler;
6
 import com.xxl.job.core.handler.IJobHandler;
8
 import com.xxl.job.core.log.XxlJobFileAppender;
7
 import com.xxl.job.core.log.XxlJobFileAppender;
9
 import com.xxl.job.core.log.XxlJobLogger;
8
 import com.xxl.job.core.log.XxlJobLogger;
32
 	private boolean toStop = false;
31
 	private boolean toStop = false;
33
 	private String stopReason;
32
 	private String stopReason;
34
 
33
 
35
-    private boolean running = false;
34
+    private boolean running = false;    // if running job
36
 
35
 
37
 
36
 
38
 	public JobThread(IJobHandler handler) {
37
 	public JobThread(IJobHandler handler) {
44
 		return handler;
43
 		return handler;
45
 	}
44
 	}
46
 
45
 
47
-	public ReturnT<String> pushTriggerQueue(TriggerParam triggerParam, ExecutorBlockStrategyEnum blockStrategy) {
46
+    /**
47
+     * new trigger to queue
48
+     *
49
+     * @param triggerParam
50
+     * @return
51
+     */
52
+	public ReturnT<String> pushTriggerQueue(TriggerParam triggerParam) {
48
 		// avoid repeat
53
 		// avoid repeat
49
 		if (triggerLogIdSet.contains(triggerParam.getLogId())) {
54
 		if (triggerLogIdSet.contains(triggerParam.getLogId())) {
50
 			logger.debug("repeate trigger job, logId:{}", triggerParam.getLogId());
55
 			logger.debug("repeate trigger job, logId:{}", triggerParam.getLogId());
51
 			return new ReturnT<String>(ReturnT.FAIL_CODE, "repeate trigger job, logId:" + triggerParam.getLogId());
56
 			return new ReturnT<String>(ReturnT.FAIL_CODE, "repeate trigger job, logId:" + triggerParam.getLogId());
52
 		}
57
 		}
53
 
58
 
54
-		// block strategy
55
-		if (ExecutorBlockStrategyEnum.DISCARD_LATER == blockStrategy) {
56
-            // discard when running
57
-            if (running) {
58
-                return new ReturnT<String>(ReturnT.FAIL_CODE, "任务阻塞:"+ExecutorBlockStrategyEnum.DISCARD_LATER.getTitle());
59
-            }
60
-		} else if (ExecutorBlockStrategyEnum.COVER_EARLY == blockStrategy) {
61
-            // kill running old and clear queue
62
-            if (running) {
63
-                this.interrupt();
64
-            }
65
-            triggerQueue.clear();
66
-            triggerLogIdSet.clear();
67
-		} else {
68
-            // just add to queue
69
-		}
70
-
71
 		triggerLogIdSet.add(triggerParam.getLogId());
59
 		triggerLogIdSet.add(triggerParam.getLogId());
72
 		triggerQueue.add(triggerParam);
60
 		triggerQueue.add(triggerParam);
73
         return ReturnT.SUCCESS;
61
         return ReturnT.SUCCESS;
74
 	}
62
 	}
75
 
63
 
64
+    /**
65
+     * kill job thread
66
+     *
67
+     * @param stopReason
68
+     */
76
 	public void toStop(String stopReason) {
69
 	public void toStop(String stopReason) {
77
 		/**
70
 		/**
78
 		 * Thread.interrupt只支持终止线程的阻塞状态(wait、join、sleep),
71
 		 * Thread.interrupt只支持终止线程的阻塞状态(wait、join、sleep),
83
 		this.stopReason = stopReason;
76
 		this.stopReason = stopReason;
84
 	}
77
 	}
85
 
78
 
79
+    /**
80
+     * is running job
81
+     * @return
82
+     */
83
+    public boolean isRunningOrHasQueue() {
84
+        return running || triggerQueue.size()>0;
85
+    }
86
 
86
 
87
-	@Override
87
+    @Override
88
 	public void run() {
88
 	public void run() {
89
 		while(!toStop){
89
 		while(!toStop){
90
 			running = false;
90
 			running = false;