Browse Source

广播分片任务

xuxueli 8 years ago
parent
commit
0c03f6348c

+ 2 - 1
doc/XXL-JOB官方文档.md View File

@@ -306,7 +306,7 @@ XXL-JOB是一个轻量级分布式任务调度框架,其核心设计目标是
306 306
 
307 307
 #### 步骤一:执行器项目中,开发JobHandler:
308 308
     - 1、 新建一个继承com.xxl.job.core.handler.IJobHandler的Java类;
309
-    - 2、 该类被Spring容器扫描为Bean实例,如加“@Service注解”
309
+    - 2、 该类被Spring容器扫描为Bean实例,如加“@Component”注解
310 310
     - 3、 添加 “@JobHander(value="自定义jobhandler名称")”注解,注解的value值为自定义的JobHandler名称,该名称对应的是调度中心新建任务的JobHandler属性的值。
311 311
     (可参考xxl-job-executor-example项目中的DemoJobHandler,见下图)
312 312
 
@@ -889,6 +889,7 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
889 889
 
890 890
 #### 6.18 版本 V1.8.1 特性[快照版本]
891 891
 - 1、任务分片:一个任务被拆分成N个独立的任务单元,然后由分布式部署的执行器分别执行某一个或几个分片单元;
892
+- 2、执行器JobHandler禁止命名冲突;
892 893
 
893 894
 #### TODO LIST
894 895
 - 1、任务权限管理:执行器为粒度分配权限,核心操作校验权限;

+ 2 - 1
xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouteStrategyEnum.java View File

@@ -15,7 +15,8 @@ public enum ExecutorRouteStrategyEnum {
15 15
     LEAST_FREQUENTLY_USED("最不经常使用", new ExecutorRouteLFU()),
16 16
     LEAST_RECENTLY_USED("最近最久未使用", new ExecutorRouteLRU()),
17 17
     FAILOVER("故障转移", new ExecutorRouteFailover()),
18
-    BUSYOVER("忙碌转移", new ExecutorRouteBusyover());
18
+    BUSYOVER("忙碌转移", new ExecutorRouteBusyover()),
19
+    BROADCAST("广播", null);
19 20
 
20 21
     ExecutorRouteStrategyEnum(String title, ExecutorRouter router) {
21 22
         this.title = title;

+ 2 - 1
xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouter.java View File

@@ -28,7 +28,7 @@ public abstract class ExecutorRouter {
28 28
      * run executor
29 29
      * @param triggerParam
30 30
      * @param address
31
-     * @return
31
+     * @return  ReturnT.content: final address
32 32
      */
33 33
     public static ReturnT<String> runExecutor(TriggerParam triggerParam, String address){
34 34
         ReturnT<String> runResult = null;
@@ -46,6 +46,7 @@ public abstract class ExecutorRouter {
46 46
         runResultSB.append("<br>msg:").append(runResult.getMsg());
47 47
 
48 48
         runResult.setMsg(runResultSB.toString());
49
+        runResult.setContent(address);
49 50
         return runResult;
50 51
     }
51 52
 

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

@@ -5,6 +5,7 @@ import com.xxl.job.admin.core.model.XxlJobGroup;
5 5
 import com.xxl.job.admin.core.model.XxlJobInfo;
6 6
 import com.xxl.job.admin.core.model.XxlJobLog;
7 7
 import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
8
+import com.xxl.job.admin.core.route.ExecutorRouter;
8 9
 import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
9 10
 import com.xxl.job.admin.core.thread.JobFailMonitorHelper;
10 11
 import com.xxl.job.core.biz.model.ReturnT;
@@ -40,6 +41,79 @@ public class XxlJobTrigger {
40 41
         ExecutorRouteStrategyEnum executorRouteStrategyEnum = ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null);    // route strategy
41 42
         ArrayList<String> addressList = (ArrayList<String>) group.getRegistryList();
42 43
 
44
+        // broadcast
45
+        if (ExecutorRouteStrategyEnum.BROADCAST == executorRouteStrategyEnum && CollectionUtils.isNotEmpty(addressList)) {
46
+            for (int i = 0; i < addressList.size(); i++) {
47
+                String address = addressList.get(i);
48
+
49
+                // 1、save log-id
50
+                XxlJobLog jobLog = new XxlJobLog();
51
+                jobLog.setJobGroup(jobInfo.getJobGroup());
52
+                jobLog.setJobId(jobInfo.getId());
53
+                XxlJobDynamicScheduler.xxlJobLogDao.save(jobLog);
54
+                logger.debug(">>>>>>>>>>> xxl-job trigger start, jobId:{}", jobLog.getId());
55
+
56
+                // 2、prepare trigger-info
57
+                //jobLog.setExecutorAddress(executorAddress);
58
+                jobLog.setGlueType(jobInfo.getGlueType());
59
+                jobLog.setExecutorHandler(jobInfo.getExecutorHandler());
60
+                jobLog.setExecutorParam(jobInfo.getExecutorParam());
61
+                jobLog.setTriggerTime(new Date());
62
+
63
+                ReturnT<String> triggerResult = new ReturnT<String>(null);
64
+                StringBuffer triggerMsgSb = new StringBuffer();
65
+                triggerMsgSb.append("注册方式:").append( (group.getAddressType() == 0)?"自动注册":"手动录入" );
66
+                triggerMsgSb.append("<br>阻塞处理策略:").append(blockStrategy.getTitle());
67
+                triggerMsgSb.append("<br>失败处理策略:").append(failStrategy.getTitle());
68
+                triggerMsgSb.append("<br>地址列表:").append(group.getRegistryList());
69
+                triggerMsgSb.append("<br>路由策略:").append(executorRouteStrategyEnum.getTitle()).append("("+i+"/"+addressList.size()+")"); // update01
70
+
71
+                // 3、trigger-valid
72
+                if (triggerResult.getCode()==ReturnT.SUCCESS_CODE && CollectionUtils.isEmpty(addressList)) {
73
+                    triggerResult.setCode(ReturnT.FAIL_CODE);
74
+                    triggerMsgSb.append("<br>----------------------<br>").append("调度失败:").append("执行器地址为空");
75
+                }
76
+
77
+                if (triggerResult.getCode() == ReturnT.SUCCESS_CODE) {
78
+                    // 4.1、trigger-param
79
+                    TriggerParam triggerParam = new TriggerParam();
80
+                    triggerParam.setJobId(jobInfo.getId());
81
+                    triggerParam.setExecutorHandler(jobInfo.getExecutorHandler());
82
+                    triggerParam.setExecutorParams(jobInfo.getExecutorParam());
83
+                    triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
84
+                    triggerParam.setLogId(jobLog.getId());
85
+                    triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime());
86
+                    triggerParam.setGlueType(jobInfo.getGlueType());
87
+                    triggerParam.setGlueSource(jobInfo.getGlueSource());
88
+                    triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
89
+                    triggerParam.setBroadcastIndex(i);
90
+                    triggerParam.setBroadcastTotal(addressList.size()); // update02
91
+
92
+                    // 4.2、trigger-run (route run / trigger remote executor)
93
+                    triggerResult = ExecutorRouter.runExecutor(triggerParam, address);     // update03
94
+                    triggerMsgSb.append("<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发调度<<<<<<<<<<< </span><br>").append(triggerResult.getMsg());
95
+
96
+                    // 4.3、trigger (fail retry)
97
+                    if (triggerResult.getCode()!=ReturnT.SUCCESS_CODE && failStrategy == ExecutorFailStrategyEnum.FAIL_RETRY) {
98
+                        triggerResult = ExecutorRouter.runExecutor(triggerParam, address);  // update04
99
+                        triggerMsgSb.append("<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>失败重试<<<<<<<<<<< </span><br>").append(triggerResult.getMsg());
100
+                    }
101
+                }
102
+
103
+                // 5、save trigger-info
104
+                jobLog.setExecutorAddress(triggerResult.getContent());
105
+                jobLog.setTriggerCode(triggerResult.getCode());
106
+                jobLog.setTriggerMsg(triggerMsgSb.toString());
107
+                XxlJobDynamicScheduler.xxlJobLogDao.updateTriggerInfo(jobLog);
108
+
109
+                // 6、monitor triger
110
+                JobFailMonitorHelper.monitor(jobLog.getId());
111
+                logger.debug(">>>>>>>>>>> xxl-job trigger end, jobId:{}", jobLog.getId());
112
+
113
+            }
114
+            return;
115
+        }
116
+
43 117
         // 1、save log-id
44 118
         XxlJobLog jobLog = new XxlJobLog();
45 119
         jobLog.setJobGroup(jobInfo.getJobGroup());
@@ -67,10 +141,6 @@ public class XxlJobTrigger {
67 141
             triggerResult.setCode(ReturnT.FAIL_CODE);
68 142
             triggerMsgSb.append("<br>----------------------<br>").append("调度失败:").append("执行器地址为空");
69 143
         }
70
-        if (triggerResult.getCode() == ReturnT.SUCCESS_CODE && executorRouteStrategyEnum == null) {
71
-            triggerResult.setCode(ReturnT.FAIL_CODE);
72
-            triggerMsgSb.append("<br>----------------------<br>").append("调度失败:").append("执行器路由策略为空");
73
-        }
74 144
 
75 145
         if (triggerResult.getCode() == ReturnT.SUCCESS_CODE) {
76 146
             // 4.1、trigger-param
@@ -79,11 +149,13 @@ public class XxlJobTrigger {
79 149
             triggerParam.setExecutorHandler(jobInfo.getExecutorHandler());
80 150
             triggerParam.setExecutorParams(jobInfo.getExecutorParam());
81 151
             triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
152
+            triggerParam.setLogId(jobLog.getId());
153
+            triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime());
82 154
             triggerParam.setGlueType(jobInfo.getGlueType());
83 155
             triggerParam.setGlueSource(jobInfo.getGlueSource());
84 156
             triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
85
-            triggerParam.setLogId(jobLog.getId());
86
-            triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime());
157
+            triggerParam.setBroadcastIndex(0);
158
+            triggerParam.setBroadcastTotal(1);
87 159
 
88 160
             // 4.2、trigger-run (route run / trigger remote executor)
89 161
             triggerResult = executorRouteStrategyEnum.getRouter().routeRun(triggerParam, addressList);

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

@@ -76,10 +76,13 @@ public class ExecutorBizImpl implements ExecutorBiz {
76 76
         // valid:jobHandler + jobThread
77 77
         if (GlueTypeEnum.BEAN==GlueTypeEnum.match(triggerParam.getGlueType())) {
78 78
 
79
+            // new jobhandler
80
+            IJobHandler newJobHandler = XxlJobExecutor.loadJobHandler(triggerParam.getExecutorHandler());
81
+
79 82
             // valid old jobThread
80
-            if (jobThread != null && jobHandler!=null && jobThread.getHandler() != jobHandler) {
83
+            if (jobThread!=null && jobHandler != newJobHandler) {
81 84
                 // change handler, need kill old thread
82
-                removeOldReason = "更JobHandler或更换任务模式,终止旧任务线程";
85
+                removeOldReason = "更JobHandler或更换任务模式,终止旧任务线程";
83 86
 
84 87
                 jobThread = null;
85 88
                 jobHandler = null;
@@ -87,7 +90,7 @@ public class ExecutorBizImpl implements ExecutorBiz {
87 90
 
88 91
             // valid handler
89 92
             if (jobHandler == null) {
90
-                jobHandler = XxlJobExecutor.loadJobHandler(triggerParam.getExecutorHandler());
93
+                jobHandler = newJobHandler;
91 94
                 if (jobHandler == null) {
92 95
                     return new ReturnT<String>(ReturnT.FAIL_CODE, "job handler [" + triggerParam.getExecutorHandler() + "] not found.");
93 96
                 }

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

@@ -14,12 +14,15 @@ public class TriggerParam implements Serializable{
14 14
     private String executorParams;
15 15
     private String executorBlockStrategy;
16 16
 
17
+    private int logId;
18
+    private long logDateTim;
19
+
17 20
     private String glueType;
18 21
     private String glueSource;
19 22
     private long glueUpdatetime;
20 23
 
21
-    private int logId;
22
-    private long logDateTim;
24
+    private int broadcastIndex;
25
+    private int broadcastTotal;
23 26
 
24 27
     public int getJobId() {
25 28
         return jobId;
@@ -53,6 +56,22 @@ public class TriggerParam implements Serializable{
53 56
         this.executorBlockStrategy = executorBlockStrategy;
54 57
     }
55 58
 
59
+    public int getLogId() {
60
+        return logId;
61
+    }
62
+
63
+    public void setLogId(int logId) {
64
+        this.logId = logId;
65
+    }
66
+
67
+    public long getLogDateTim() {
68
+        return logDateTim;
69
+    }
70
+
71
+    public void setLogDateTim(long logDateTim) {
72
+        this.logDateTim = logDateTim;
73
+    }
74
+
56 75
     public String getGlueType() {
57 76
         return glueType;
58 77
     }
@@ -77,20 +96,20 @@ public class TriggerParam implements Serializable{
77 96
         this.glueUpdatetime = glueUpdatetime;
78 97
     }
79 98
 
80
-    public int getLogId() {
81
-        return logId;
99
+    public int getBroadcastIndex() {
100
+        return broadcastIndex;
82 101
     }
83 102
 
84
-    public void setLogId(int logId) {
85
-        this.logId = logId;
103
+    public void setBroadcastIndex(int broadcastIndex) {
104
+        this.broadcastIndex = broadcastIndex;
86 105
     }
87 106
 
88
-    public long getLogDateTim() {
89
-        return logDateTim;
107
+    public int getBroadcastTotal() {
108
+        return broadcastTotal;
90 109
     }
91 110
 
92
-    public void setLogDateTim(long logDateTim) {
93
-        this.logDateTim = logDateTim;
111
+    public void setBroadcastTotal(int broadcastTotal) {
112
+        this.broadcastTotal = broadcastTotal;
94 113
     }
95 114
 
96 115
     @Override
@@ -100,11 +119,14 @@ public class TriggerParam implements Serializable{
100 119
                 ", executorHandler='" + executorHandler + '\'' +
101 120
                 ", executorParams='" + executorParams + '\'' +
102 121
                 ", executorBlockStrategy='" + executorBlockStrategy + '\'' +
122
+                ", logId=" + logId +
123
+                ", logDateTim=" + logDateTim +
103 124
                 ", glueType='" + glueType + '\'' +
104 125
                 ", glueSource='" + glueSource + '\'' +
105 126
                 ", glueUpdatetime=" + glueUpdatetime +
106
-                ", logId=" + logId +
107
-                ", logDateTim=" + logDateTim +
127
+                ", broadcastIndex=" + broadcastIndex +
128
+                ", broadcastTotal=" + broadcastTotal +
108 129
                 '}';
109 130
     }
131
+
110 132
 }

+ 3 - 0
xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java View File

@@ -98,6 +98,9 @@ public class XxlJobExecutor implements ApplicationContextAware, ApplicationListe
98 98
                 if (serviceBean instanceof IJobHandler){
99 99
                     String name = serviceBean.getClass().getAnnotation(JobHander.class).value();
100 100
                     IJobHandler handler = (IJobHandler) serviceBean;
101
+                    if (loadJobHandler(name) != null) {
102
+                        throw new RuntimeException("xxl-job jobhandler naming conflicts.");
103
+                    }
101 104
                     registJobHandler(name, handler);
102 105
                 }
103 106
             }

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

@@ -18,8 +18,8 @@ public class XxlJobFileAppender {
18 18
 	
19 19
 	// for JobThread (support log for child thread of job handler)
20 20
 	//public static ThreadLocal<String> contextHolder = new ThreadLocal<String>();
21
-	public static InheritableThreadLocal<String> contextHolder = new InheritableThreadLocal<String>();
22
-	public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
21
+	public static final InheritableThreadLocal<String> contextHolder = new InheritableThreadLocal<String>();
22
+	public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
23 23
 	
24 24
 	/**
25 25
 	 * log filename: yyyy-MM-dd/9999.log

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

@@ -7,6 +7,7 @@ import com.xxl.job.core.executor.XxlJobExecutor;
7 7
 import com.xxl.job.core.handler.IJobHandler;
8 8
 import com.xxl.job.core.log.XxlJobFileAppender;
9 9
 import com.xxl.job.core.log.XxlJobLogger;
10
+import com.xxl.job.core.util.ShardingUtil;
10 11
 import org.eclipse.jetty.util.ConcurrentHashSet;
11 12
 import org.slf4j.Logger;
12 13
 import org.slf4j.LoggerFactory;
@@ -112,6 +113,7 @@ public class JobThread extends Thread{
112 113
 						String logFileName = XxlJobFileAppender.makeLogFileName(new Date(triggerParam.getLogDateTim()), triggerParam.getLogId());
113 114
 
114 115
 						XxlJobFileAppender.contextHolder.set(logFileName);
116
+						ShardingUtil.setShardingVo(new ShardingUtil.ShardingVO(triggerParam.getBroadcastIndex(), triggerParam.getBroadcastTotal()));
115 117
 						XxlJobLogger.log("<br>----------- xxl-job job execute start -----------<br>----------- Params:" + Arrays.toString(handlerParams));
116 118
 
117 119
 						executeResult = handler.execute(handlerParams);

+ 46 - 0
xxl-job-core/src/main/java/com/xxl/job/core/util/ShardingUtil.java View File

@@ -0,0 +1,46 @@
1
+package com.xxl.job.core.util;
2
+
3
+/**
4
+ * sharding vo
5
+ * @author xuxueli 2017-07-25 21:26:38
6
+ */
7
+public class ShardingUtil {
8
+
9
+    private static InheritableThreadLocal<ShardingVO> contextHolder = new InheritableThreadLocal<ShardingVO>();
10
+
11
+    public static class ShardingVO {
12
+
13
+        private int index;  // sharding index
14
+        private int total;  // sharding total
15
+
16
+        public ShardingVO(int index, int total) {
17
+            this.index = index;
18
+            this.total = total;
19
+        }
20
+
21
+        public int getIndex() {
22
+            return index;
23
+        }
24
+
25
+        public void setIndex(int index) {
26
+            this.index = index;
27
+        }
28
+
29
+        public int getTotal() {
30
+            return total;
31
+        }
32
+
33
+        public void setTotal(int total) {
34
+            this.total = total;
35
+        }
36
+    }
37
+
38
+    public static void setShardingVo(ShardingVO shardingVo){
39
+        contextHolder.set(shardingVo);
40
+    }
41
+
42
+    public static ShardingVO getShardingVo(){
43
+        return contextHolder.get();
44
+    }
45
+
46
+}

+ 5 - 5
xxl-job-executor-example/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java View File

@@ -4,7 +4,7 @@ import com.xxl.job.core.biz.model.ReturnT;
4 4
 import com.xxl.job.core.handler.IJobHandler;
5 5
 import com.xxl.job.core.handler.annotation.JobHander;
6 6
 import com.xxl.job.core.log.XxlJobLogger;
7
-import org.springframework.stereotype.Service;
7
+import org.springframework.stereotype.Component;
8 8
 
9 9
 import java.util.concurrent.TimeUnit;
10 10
 
@@ -13,15 +13,15 @@ import java.util.concurrent.TimeUnit;
13 13
  * 任务Handler的一个Demo(Bean模式)
14 14
  * 
15 15
  * 开发步骤:
16
- * 1、继承 “IJobHandler” 
17
- * 2、装配到Spring,例如加 “@Service” 注解;
18
- * 3、加 “@JobHander” 注解,注解value值为新增任务生成的JobKey的值;多个JobKey用逗号分割;
16
+ * 1、新建一个继承com.xxl.job.core.handler.IJobHandler的Java类
17
+ * 2、该类被Spring容器扫描为Bean实例,如加“@Component”注解;
18
+ * 3、添加 “@JobHander(value="自定义jobhandler名称")”注解,注解的value值为自定义的JobHandler名称,该名称对应的是调度中心新建任务的JobHandler属性的值。
19 19
  * 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
20 20
  * 
21 21
  * @author xuxueli 2015-12-19 19:43:36
22 22
  */
23 23
 @JobHander(value="demoJobHandler")
24
-@Service
24
+@Component
25 25
 public class DemoJobHandler extends IJobHandler {
26 26
 
27 27
 	@Override

+ 39 - 0
xxl-job-executor-example/src/main/java/com/xxl/job/executor/service/jobhandler/ShardingJobHandler.java View File

@@ -0,0 +1,39 @@
1
+package com.xxl.job.executor.service.jobhandler;
2
+
3
+import com.xxl.job.core.biz.model.ReturnT;
4
+import com.xxl.job.core.handler.IJobHandler;
5
+import com.xxl.job.core.handler.annotation.JobHander;
6
+import com.xxl.job.core.log.XxlJobLogger;
7
+import com.xxl.job.core.util.ShardingUtil;
8
+import org.springframework.stereotype.Service;
9
+
10
+
11
+/**
12
+ * 广播分片任务
13
+ *
14
+ * @author xuxueli 2017-07-25 20:56:50
15
+ */
16
+@JobHander(value="shardingJobHandler")
17
+@Service
18
+public class ShardingJobHandler extends IJobHandler {
19
+
20
+	@Override
21
+	public ReturnT<String> execute(String... params) throws Exception {
22
+
23
+		// 分片参数
24
+		ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();
25
+		XxlJobLogger.log("分片参数:当前分片序号 = {0}, 总分片数 = {1}", shardingVO.getIndex(), shardingVO.getTotal());
26
+
27
+		// 业务逻辑
28
+		for (int i = 0; i < shardingVO.getTotal(); i++) {
29
+			if (i == shardingVO.getIndex()) {
30
+				XxlJobLogger.log("第 {0} 片, 命中分片开始处理", i);
31
+			} else {
32
+				XxlJobLogger.log("第 {0} 片, 忽略", i);
33
+			}
34
+		}
35
+
36
+		return ReturnT.SUCCESS;
37
+	}
38
+	
39
+}

+ 39 - 0
xxl-job-executor-springboot-example/src/main/java/com/xxl/job/executor/service/jobhandler/ShardingJobHandler.java View File

@@ -0,0 +1,39 @@
1
+package com.xxl.job.executor.service.jobhandler;
2
+
3
+import com.xxl.job.core.biz.model.ReturnT;
4
+import com.xxl.job.core.handler.IJobHandler;
5
+import com.xxl.job.core.handler.annotation.JobHander;
6
+import com.xxl.job.core.log.XxlJobLogger;
7
+import com.xxl.job.core.util.ShardingUtil;
8
+import org.springframework.stereotype.Service;
9
+
10
+
11
+/**
12
+ * 广播分片任务
13
+ *
14
+ * @author xuxueli 2017-07-25 20:56:50
15
+ */
16
+@JobHander(value="shardingJobHandler")
17
+@Service
18
+public class ShardingJobHandler extends IJobHandler {
19
+
20
+	@Override
21
+	public ReturnT<String> execute(String... params) throws Exception {
22
+
23
+		// 分片参数
24
+		ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();
25
+		XxlJobLogger.log("分片参数:当前分片序号 = {0}, 总分片数 = {1}", shardingVO.getIndex(), shardingVO.getTotal());
26
+
27
+		// 业务逻辑
28
+		for (int i = 0; i < shardingVO.getTotal(); i++) {
29
+			if (i == shardingVO.getIndex()) {
30
+				XxlJobLogger.log("第 {0} 片, 命中分片开始处理", i);
31
+			} else {
32
+				XxlJobLogger.log("第 {0} 片, 忽略", i);
33
+			}
34
+		}
35
+
36
+		return ReturnT.SUCCESS;
37
+	}
38
+
39
+}