|
@@ -3,6 +3,7 @@ package com.xxl.job.admin.core.jobbean;
|
3
|
3
|
import com.xxl.job.admin.core.model.XxlJobGroup;
|
4
|
4
|
import com.xxl.job.admin.core.model.XxlJobInfo;
|
5
|
5
|
import com.xxl.job.admin.core.model.XxlJobLog;
|
|
6
|
+import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
|
6
|
7
|
import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
|
7
|
8
|
import com.xxl.job.admin.core.thread.JobMonitorHelper;
|
8
|
9
|
import com.xxl.job.admin.core.thread.JobRegistryHelper;
|
|
@@ -11,6 +12,7 @@ import com.xxl.job.core.biz.model.ReturnT;
|
11
|
12
|
import com.xxl.job.core.biz.model.TriggerParam;
|
12
|
13
|
import com.xxl.job.core.registry.RegistHelper;
|
13
|
14
|
import com.xxl.job.core.rpc.netcom.NetComClientProxy;
|
|
15
|
+import org.apache.commons.collections.CollectionUtils;
|
14
|
16
|
import org.apache.commons.lang.StringUtils;
|
15
|
17
|
import org.quartz.JobExecutionContext;
|
16
|
18
|
import org.quartz.JobExecutionException;
|
|
@@ -19,7 +21,6 @@ import org.slf4j.Logger;
|
19
|
21
|
import org.slf4j.LoggerFactory;
|
20
|
22
|
import org.springframework.scheduling.quartz.QuartzJobBean;
|
21
|
23
|
|
22
|
|
-import java.text.MessageFormat;
|
23
|
24
|
import java.util.*;
|
24
|
25
|
|
25
|
26
|
/**
|
|
@@ -34,26 +35,23 @@ public class RemoteHttpJobBean extends QuartzJobBean {
|
34
|
35
|
@Override
|
35
|
36
|
protected void executeInternal(JobExecutionContext context)
|
36
|
37
|
throws JobExecutionException {
|
|
38
|
+
|
|
39
|
+ // load job
|
37
|
40
|
JobKey jobKey = context.getTrigger().getJobKey();
|
38
|
41
|
Integer jobId = Integer.valueOf(jobKey.getName());
|
39
|
42
|
XxlJobInfo jobInfo = XxlJobDynamicScheduler.xxlJobInfoDao.loadById(jobId);
|
40
|
43
|
|
41
|
|
- // save log
|
|
44
|
+ // log part-1
|
42
|
45
|
XxlJobLog jobLog = new XxlJobLog();
|
43
|
46
|
jobLog.setJobGroup(jobInfo.getJobGroup());
|
44
|
47
|
jobLog.setJobId(jobInfo.getId());
|
45
|
48
|
XxlJobDynamicScheduler.xxlJobLogDao.save(jobLog);
|
46
|
49
|
logger.debug(">>>>>>>>>>> xxl-job trigger start, jobId:{}", jobLog.getId());
|
47
|
50
|
|
48
|
|
- // admin address
|
49
|
|
- List<String> adminAddressList = JobRegistryHelper.discover(RegistHelper.RegistType.ADMIN.name(), RegistHelper.RegistType.ADMIN.name());
|
50
|
|
- Set<String> adminAddressSet = new HashSet<String>();
|
51
|
|
- if (adminAddressList!=null) {
|
52
|
|
- adminAddressSet.addAll(adminAddressList);
|
53
|
|
- }
|
54
|
|
- adminAddressSet.add(XxlJobDynamicScheduler.getCallbackAddress());
|
55
|
|
-
|
56
|
|
- // update trigger info 1/2
|
|
51
|
+ // log part-2 param
|
|
52
|
+ //jobLog.setExecutorAddress(executorAddress);
|
|
53
|
+ jobLog.setExecutorHandler(jobInfo.getExecutorHandler());
|
|
54
|
+ jobLog.setExecutorParam(jobInfo.getExecutorParam());
|
57
|
55
|
jobLog.setTriggerTime(new Date());
|
58
|
56
|
|
59
|
57
|
// trigger request
|
|
@@ -64,114 +62,152 @@ public class RemoteHttpJobBean extends QuartzJobBean {
|
64
|
62
|
triggerParam.setGlueSwitch((jobInfo.getGlueSwitch()==0)?false:true);
|
65
|
63
|
triggerParam.setLogId(jobLog.getId());
|
66
|
64
|
triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime());
|
67
|
|
- triggerParam.setLogAddress(adminAddressSet);
|
68
|
|
-
|
69
|
|
- // parse address
|
70
|
|
- String groupAddressInfo = "注册方式:";
|
71
|
|
- List<String> addressList = new ArrayList<String>();
|
72
|
|
- XxlJobGroup group = XxlJobDynamicScheduler.xxlJobGroupDao.load(Integer.valueOf(jobInfo.getJobGroup()));
|
73
|
|
- if (group!=null) {
|
74
|
|
- if (group.getAddressType() == 0) {
|
75
|
|
- groupAddressInfo += "自动注册";
|
76
|
|
- addressList = JobRegistryHelper.discover(RegistHelper.RegistType.EXECUTOR.name(), group.getAppName());
|
77
|
|
- } else {
|
78
|
|
- groupAddressInfo += "手动录入";
|
79
|
|
- if (StringUtils.isNotBlank(group.getAddressList())) {
|
80
|
|
- addressList = Arrays.asList(group.getAddressList().split(","));
|
81
|
|
- }
|
82
|
|
- }
|
83
|
|
- groupAddressInfo += ",地址列表:" + addressList.toString();
|
84
|
|
- }
|
85
|
|
- groupAddressInfo += "<br><br>";
|
|
65
|
+ triggerParam.setLogAddress(findCallbackAddressList()); // callback address list
|
86
|
66
|
|
87
|
|
- // failover trigger
|
88
|
|
- ReturnT<String> triggerResult = failoverTrigger(addressList, triggerParam, jobLog);
|
89
|
|
- jobLog.setExecutorHandler(jobInfo.getExecutorHandler());
|
90
|
|
- jobLog.setExecutorParam(jobInfo.getExecutorParam());
|
91
|
|
- logger.info(">>>>>>>>>>> xxl-job failoverTrigger, jobId:{}, triggerResult:{}", jobLog.getId(), triggerResult.toString());
|
92
|
|
-
|
93
|
|
- // update trigger info 2/2
|
|
67
|
+ // do trigger
|
|
68
|
+ ReturnT<String> triggerResult = doTrigger(triggerParam, jobInfo, jobLog);
|
|
69
|
+
|
|
70
|
+ // log part-2
|
94
|
71
|
jobLog.setTriggerCode(triggerResult.getCode());
|
95
|
|
- jobLog.setTriggerMsg(groupAddressInfo + triggerResult.getMsg());
|
|
72
|
+ jobLog.setTriggerMsg(triggerResult.getMsg());
|
96
|
73
|
XxlJobDynamicScheduler.xxlJobLogDao.updateTriggerInfo(jobLog);
|
97
|
74
|
|
98
|
75
|
// monitor triger
|
99
|
76
|
JobMonitorHelper.monitor(jobLog.getId());
|
100
|
|
-
|
101
|
77
|
logger.debug(">>>>>>>>>>> xxl-job trigger end, jobId:{}", jobLog.getId());
|
102
|
78
|
}
|
103
|
|
-
|
104
|
|
-
|
105
|
|
- /**
|
106
|
|
- * failover for trigger remote address
|
107
|
|
- * @return
|
108
|
|
- */
|
109
|
|
- public ReturnT<String> failoverTrigger(List<String> addressList, TriggerParam triggerParam, XxlJobLog jobLog){
|
110
|
|
- if (addressList==null || addressList.size() < 1) {
|
111
|
|
- return new ReturnT<String>(ReturnT.FAIL_CODE, "Trigger error, <br>>>>[address] is null <br><hr>");
|
112
|
|
- } else if (addressList.size() == 1) {
|
113
|
|
- String address = addressList.get(0);
|
114
|
|
- // store real address
|
115
|
|
- jobLog.setExecutorAddress(address);
|
116
|
|
-
|
117
|
|
- // real trigger
|
118
|
|
- ExecutorBiz executorBiz = null;
|
119
|
|
- try {
|
120
|
|
- executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address).getObject();
|
121
|
|
- } catch (Exception e) {
|
122
|
|
- e.printStackTrace();
|
123
|
|
- return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());
|
124
|
|
- }
|
125
|
|
- ReturnT<String> runResult = executorBiz.run(triggerParam);
|
126
|
|
-
|
127
|
|
- String failoverMessage = MessageFormat.format("Trigger running, <br>>>>[address] : {0}, <br>>>>[code] : {1}, <br>>>>[msg] : {2} <br><hr>",
|
128
|
|
- address, runResult.getCode(), runResult.getMsg());
|
129
|
|
- runResult.setMsg(runResult.getMsg() + failoverMessage);
|
130
|
|
- return runResult;
|
131
|
|
- } else {
|
132
|
|
-
|
133
|
|
- // for ha
|
134
|
|
- Collections.shuffle(addressList);
|
135
|
|
-
|
136
|
|
- // for failover
|
137
|
|
- String failoverMessage = "";
|
138
|
|
- for (String address : addressList) {
|
139
|
|
- if (StringUtils.isNotBlank(address)) {
|
140
|
|
-
|
141
|
|
-
|
142
|
|
- ExecutorBiz executorBiz = null;
|
143
|
|
- try {
|
144
|
|
- executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address).getObject();
|
145
|
|
- } catch (Exception e) {
|
146
|
|
- e.printStackTrace();
|
147
|
|
- return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());
|
148
|
|
- }
|
149
|
|
-
|
150
|
|
- // beat check
|
151
|
|
- ReturnT<String> beatResult = executorBiz.beat();
|
152
|
|
- failoverMessage += MessageFormat.format("BEAT running, <br>>>>[address] : {0}, <br>>>>[code] : {1}, <br>>>>[msg] : {2} <br><hr>",
|
153
|
|
- address, beatResult.getCode(), beatResult.getMsg());
|
154
|
|
-
|
155
|
|
- // beat success, trigger do
|
|
79
|
+
|
|
80
|
+ public ReturnT<String> doTrigger(TriggerParam triggerParam, XxlJobInfo jobInfo, XxlJobLog jobLog){
|
|
81
|
+ StringBuffer triggerSb = new StringBuffer();
|
|
82
|
+
|
|
83
|
+ // exerutor address list
|
|
84
|
+ ArrayList<String> addressList = null;
|
|
85
|
+ XxlJobGroup group = XxlJobDynamicScheduler.xxlJobGroupDao.load(jobInfo.getJobGroup());
|
|
86
|
+ if (group.getAddressType() == 0) {
|
|
87
|
+ triggerSb.append("注册方式:自动注册");
|
|
88
|
+ addressList = (ArrayList<String>) JobRegistryHelper.discover(RegistHelper.RegistType.EXECUTOR.name(), group.getAppName());
|
|
89
|
+ } else {
|
|
90
|
+ triggerSb.append("注册方式:手动录入");
|
|
91
|
+ if (StringUtils.isNotBlank(group.getAddressList())) {
|
|
92
|
+ addressList = new ArrayList<String>(Arrays.asList(group.getAddressList().split(",")));
|
|
93
|
+ }
|
|
94
|
+ }
|
|
95
|
+ triggerSb.append("<br>地址列表:").append(addressList!=null?addressList.toString():"");
|
|
96
|
+ if (CollectionUtils.isEmpty(addressList)) {
|
|
97
|
+ triggerSb.append("<hr>调度失败:").append("执行器地址为空");
|
|
98
|
+ return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
|
|
99
|
+ }
|
|
100
|
+
|
|
101
|
+ // trigger remote executor
|
|
102
|
+ if (addressList.size() == 1) {
|
|
103
|
+ String address = addressList.get(0);
|
|
104
|
+ jobLog.setExecutorAddress(address);
|
|
105
|
+
|
|
106
|
+ ReturnT<String> runResult = runExecutor(triggerParam, address);
|
|
107
|
+ triggerSb.append("<hr>").append(runResult.getMsg());
|
|
108
|
+
|
|
109
|
+ return new ReturnT<String>(runResult.getCode(), triggerSb.toString());
|
|
110
|
+ } else {
|
|
111
|
+ // executor route strategy
|
|
112
|
+ ExecutorRouteStrategyEnum executorRouteStrategyEnum = ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null);
|
|
113
|
+ triggerSb.append("<br>路由策略:").append(executorRouteStrategyEnum!=null?(executorRouteStrategyEnum.name() + "-" + executorRouteStrategyEnum.getTitle()):null);
|
|
114
|
+ if (executorRouteStrategyEnum == null) {
|
|
115
|
+ triggerSb.append("<hr>调度失败:").append("执行器路由策略为空");
|
|
116
|
+ return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
|
|
117
|
+ }
|
|
118
|
+
|
|
119
|
+ if (executorRouteStrategyEnum != ExecutorRouteStrategyEnum.FAILOVER) {
|
|
120
|
+ // get address
|
|
121
|
+ String address = executorRouteStrategyEnum.getRouter().route(jobInfo.getId(), addressList);
|
|
122
|
+ jobLog.setExecutorAddress(address);
|
|
123
|
+
|
|
124
|
+ // run
|
|
125
|
+ ReturnT<String> runResult = runExecutor(triggerParam, address);
|
|
126
|
+ triggerSb.append("<hr>").append(runResult.getMsg());
|
|
127
|
+
|
|
128
|
+ return new ReturnT<String>(runResult.getCode(), triggerSb.toString());
|
|
129
|
+ } else {
|
|
130
|
+ for (String address : addressList) {
|
|
131
|
+ // beat
|
|
132
|
+ ReturnT<String> beatResult = beatExecutor(address);
|
|
133
|
+ triggerSb.append("<hr>").append(beatResult.getMsg());
|
|
134
|
+
|
156
|
135
|
if (beatResult.getCode() == ReturnT.SUCCESS_CODE) {
|
157
|
|
- // store real address
|
158
|
136
|
jobLog.setExecutorAddress(address);
|
159
|
137
|
|
160
|
|
- // real trigger
|
161
|
|
- ReturnT<String> runResult = executorBiz.run(triggerParam);
|
|
138
|
+ ReturnT<String> runResult = runExecutor(triggerParam, address);
|
|
139
|
+ triggerSb.append("<hr>").append(runResult.getMsg());
|
162
|
140
|
|
163
|
|
- failoverMessage += MessageFormat.format("Trigger running, <br>>>>[address] : {0}, <br>>>>[status] : {1}, <br>>>>[msg] : {2} <br><hr>",
|
164
|
|
- address, runResult.getCode(), runResult.getMsg());
|
165
|
|
- runResult.setMsg( runResult.getMsg() + failoverMessage);
|
166
|
|
- return runResult;
|
|
141
|
+ return new ReturnT<String>(runResult.getCode(), triggerSb.toString());
|
167
|
142
|
}
|
168
|
|
-
|
169
|
143
|
}
|
|
144
|
+ return new ReturnT<String>(ReturnT.FAIL_CODE, triggerSb.toString());
|
170
|
145
|
}
|
|
146
|
+ }
|
|
147
|
+ }
|
|
148
|
+
|
|
149
|
+ /**
|
|
150
|
+ * run executor
|
|
151
|
+ * @param address
|
|
152
|
+ * @return
|
|
153
|
+ */
|
|
154
|
+ public ReturnT<String> beatExecutor(String address){
|
|
155
|
+ ReturnT<String> beatResult = null;
|
|
156
|
+ try {
|
|
157
|
+ ExecutorBiz executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address).getObject();
|
|
158
|
+ beatResult = executorBiz.beat();
|
|
159
|
+ } catch (Exception e) {
|
|
160
|
+ logger.error("", e);
|
|
161
|
+ beatResult = new ReturnT<String>(ReturnT.FAIL_CODE, ""+e );
|
|
162
|
+ }
|
|
163
|
+
|
|
164
|
+ StringBuffer sb = new StringBuffer("心跳检测:");
|
|
165
|
+ sb.append("<br>address:").append(address);
|
|
166
|
+ sb.append("<br>code:").append(beatResult.getCode());
|
|
167
|
+ sb.append("<br>msg:").append(beatResult.getMsg());
|
|
168
|
+ beatResult.setMsg(sb.toString());
|
|
169
|
+
|
|
170
|
+ return beatResult;
|
|
171
|
+ }
|
|
172
|
+
|
|
173
|
+ /**
|
|
174
|
+ * run executor
|
|
175
|
+ * @param triggerParam
|
|
176
|
+ * @param address
|
|
177
|
+ * @return
|
|
178
|
+ */
|
|
179
|
+ public ReturnT<String> runExecutor(TriggerParam triggerParam, String address){
|
|
180
|
+ ReturnT<String> runResult = null;
|
|
181
|
+ try {
|
|
182
|
+ ExecutorBiz executorBiz = (ExecutorBiz) new NetComClientProxy(ExecutorBiz.class, address).getObject();
|
|
183
|
+ runResult = executorBiz.run(triggerParam);
|
|
184
|
+ } catch (Exception e) {
|
|
185
|
+ logger.error("", e);
|
|
186
|
+ runResult = new ReturnT<String>(ReturnT.FAIL_CODE, ""+e );
|
|
187
|
+ }
|
|
188
|
+
|
|
189
|
+ StringBuffer sb = new StringBuffer("触发调度:");
|
|
190
|
+ sb.append("<br>address:").append(address);
|
|
191
|
+ sb.append("<br>code:").append(runResult.getCode());
|
|
192
|
+ sb.append("<br>msg:").append(runResult.getMsg());
|
|
193
|
+ runResult.setMsg(sb.toString());
|
|
194
|
+
|
|
195
|
+ return runResult;
|
|
196
|
+ }
|
|
197
|
+
|
|
198
|
+ /**
|
|
199
|
+ * find callback address list
|
|
200
|
+ * @return
|
|
201
|
+ */
|
|
202
|
+ public Set<String> findCallbackAddressList(){
|
|
203
|
+ Set<String> adminAddressSet = new HashSet<String>();
|
|
204
|
+ adminAddressSet.add(XxlJobDynamicScheduler.getCallbackAddress());
|
171
|
205
|
|
172
|
|
- return new ReturnT<String>(ReturnT.FAIL_CODE, failoverMessage);
|
|
206
|
+ List<String> adminAddressList = JobRegistryHelper.discover(RegistHelper.RegistType.ADMIN.name(), RegistHelper.RegistType.ADMIN.name());
|
|
207
|
+ if (adminAddressList!=null) {
|
|
208
|
+ adminAddressSet.addAll(adminAddressList);
|
173
|
209
|
}
|
|
210
|
+ return adminAddressSet;
|
174
|
211
|
}
|
175
|
212
|
|
176
|
|
-
|
177
|
213
|
}
|