소스 검색

1、任务新增"执行器路由策略"属性;
2、路由策略逻辑:第一个、最后一个、轮训、随机、一致性HASH

xueli.xue 8 년 전
부모
커밋
9c03285d94

+ 2 - 2
db/tables_xxl_job.sql

@@ -145,7 +145,7 @@ CREATE TABLE XXL_JOB_QRTZ_LOCKS
 
 
 
 
 
 
-CREATE TABLE XXL_JOB_QRTZ_TRIGGER_INFO (
+CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_INFO` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `job_group` int(11) NOT NULL COMMENT '任务组(执行器ID)',
   `job_group` int(11) NOT NULL COMMENT '任务组(执行器ID)',
   `job_name` varchar(255) NOT NULL COMMENT '任务名',
   `job_name` varchar(255) NOT NULL COMMENT '任务名',
@@ -155,6 +155,7 @@ CREATE TABLE XXL_JOB_QRTZ_TRIGGER_INFO (
   `update_time` datetime DEFAULT NULL,
   `update_time` datetime DEFAULT NULL,
   `author` varchar(64) DEFAULT NULL COMMENT '作者',
   `author` varchar(64) DEFAULT NULL COMMENT '作者',
   `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
   `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
+  `executor_route_strategy` varchar(20) DEFAULT NULL COMMENT '执行器路由策略',
   `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
   `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
   `executor_param` varchar(255) DEFAULT NULL COMMENT '执行器任务参数',
   `executor_param` varchar(255) DEFAULT NULL COMMENT '执行器任务参数',
   `glue_switch` int(11) DEFAULT '0' COMMENT 'GLUE模式开关:0-否,1-是',
   `glue_switch` int(11) DEFAULT '0' COMMENT 'GLUE模式开关:0-否,1-是',
@@ -164,7 +165,6 @@ CREATE TABLE XXL_JOB_QRTZ_TRIGGER_INFO (
   PRIMARY KEY (`id`)
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
 
-
 CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOG` (
 CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOG` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `job_group` int(11) NOT NULL COMMENT '任务组',
   `job_group` int(11) NOT NULL COMMENT '任务组',

+ 12 - 3
xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobInfo.java

@@ -21,8 +21,9 @@ public class XxlJobInfo {
 	private String author;		// 负责人
 	private String author;		// 负责人
 	private String alarmEmail;	// 报警邮件
 	private String alarmEmail;	// 报警邮件
 
 
-	private String executorHandler;	// 执行器,任务Handler名称
-	private String executorParam;	// 执行器,任务参数
+	private String executorRouteStrategy;	// 执行器路由策略
+	private String executorHandler;		    // 执行器,任务Handler名称
+	private String executorParam;		    // 执行器,任务参数
 	
 	
 	private int glueSwitch;		// GLUE模式开关:0-否,1-是
 	private int glueSwitch;		// GLUE模式开关:0-否,1-是
 	private String glueSource;	// GLUE源代码
 	private String glueSource;	// GLUE源代码
@@ -105,7 +106,15 @@ public class XxlJobInfo {
 		this.alarmEmail = alarmEmail;
 		this.alarmEmail = alarmEmail;
 	}
 	}
 
 
-	public String getExecutorHandler() {
+    public String getExecutorRouteStrategy() {
+        return executorRouteStrategy;
+    }
+
+    public void setExecutorRouteStrategy(String executorRouteStrategy) {
+        this.executorRouteStrategy = executorRouteStrategy;
+    }
+
+    public String getExecutorHandler() {
 		return executorHandler;
 		return executorHandler;
 	}
 	}
 
 

+ 41 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouteStrategyEnum.java

@@ -0,0 +1,41 @@
+package com.xxl.job.admin.core.route;
+
+import com.xxl.job.admin.core.route.strategy.*;
+
+/**
+ * Created by xuxueli on 17/3/10.
+ */
+public enum ExecutorRouteStrategyEnum {
+
+    FIRST("第一个", new ExecutorRouteFirst()),
+    LAST("最后一个", new ExecutorRouteLast()),
+    ROUND("轮询", new ExecutorRouteRound()),
+    RANDOM("随机", new ExecutorRouteRandom()),
+    CONSISTENT_HASH("一致性HASH", new ExecutorRouteConsistentHash()),
+    FAILOVER("故障转移", null);
+
+    ExecutorRouteStrategyEnum(String title, ExecutorRouter router) {
+        this.title = title;
+        this.router = router;
+    }
+
+    private String title;
+    private ExecutorRouter router;
+
+    public String getTitle() {
+        return title;
+    }
+    public ExecutorRouter getRouter() {
+        return router;
+    }
+
+    public static ExecutorRouteStrategyEnum match(String name, ExecutorRouteStrategyEnum defaultItem){
+        for (ExecutorRouteStrategyEnum item: ExecutorRouteStrategyEnum.values()) {
+            if (item.name().equals(name)) {
+                return item;
+            }
+        }
+        return defaultItem;
+    }
+
+}

+ 51 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouter.java

@@ -0,0 +1,51 @@
+package com.xxl.job.admin.core.route;
+
+import org.apache.commons.collections.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Created by xuxueli on 17/3/10.
+ */
+public abstract class ExecutorRouter {
+
+    public abstract String route(int jobId, ArrayList<String> addressList);
+
+    public static String route(int jobId, ArrayList<String> addressList, String executorRouteStrategy){
+        if (CollectionUtils.isEmpty(addressList)) {
+            return null;
+        }
+        ExecutorRouteStrategyEnum strategy = ExecutorRouteStrategyEnum.match(executorRouteStrategy, ExecutorRouteStrategyEnum.FIRST);
+        String routeAddress = strategy.getRouter().route(jobId, addressList);
+        return routeAddress;
+    }
+
+    public static void main(String[] args) {
+
+        int c1 = 0;
+        int c2 = 0;
+        int c3 = 0;
+
+        long start = System.currentTimeMillis();
+        for (int i = 0; i < 10; i++) {
+            String ret = ExecutorRouter.route(i, new ArrayList<String>(Arrays.asList("127.0.0.1:0000", "127.0.0.1:2222", "127.0.0.1:3333")), ExecutorRouteStrategyEnum.CONSISTENT_HASH.name());
+            if (ret.equals("127.0.0.1:0000")) {
+                c1++;
+            } else if (ret.equals("127.0.0.1:2222")) {
+                c2++;
+            } else if (ret.equals("127.0.0.1:3333")) {
+                c3++;
+            }
+        }
+        long end = System.currentTimeMillis();
+        System.out.println(end - start);    // 1000*100=740、1000*1=162、
+
+
+        System.out.println(c1);
+        System.out.println(c2);
+        System.out.println(c3);
+
+    }
+
+}

+ 80 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteConsistentHash.java

@@ -0,0 +1,80 @@
+package com.xxl.job.admin.core.route.strategy;
+
+import com.xxl.job.admin.core.route.ExecutorRouter;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * 分组下JOB均匀散列在不同机器上;且每个JOB固定调度其中一台机器;
+ *      a、virtual node:解决不均衡问题
+ *      b、hash method replace hashCode:String的hashCode可能重复,需要进一步扩大hashCode的取值范围
+ * Created by xuxueli on 17/3/10.
+ */
+public class ExecutorRouteConsistentHash extends ExecutorRouter {
+
+    private static int VIRTUAL_NODE_NUM = 5;
+
+    @Override
+    public String route(int jobId, ArrayList<String> addressList) {
+
+        // ------A1------A2-------A3------
+        // -----------J1------------------
+        TreeMap<Long, String> addressRing = new TreeMap<Long, String>();
+        for (String address: addressList) {
+            for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {
+                long addressHash = hash("SHARD-" + address + "-NODE-" + i);
+                addressRing.put(addressHash, address);
+            }
+        }
+
+        long jobHash = hash(String.valueOf(jobId));
+        SortedMap<Long, String> lastRing = addressRing.tailMap(jobHash);
+        if (!lastRing.isEmpty()) {
+            return lastRing.get(lastRing.firstKey());
+        }
+        return addressRing.firstEntry().getValue();
+    }
+
+
+
+    /**
+     * get hash code on 2^32 ring (md5散列的方式计算hash值)
+     * @param key
+     * @return
+     */
+    private static long hash(String key) {
+
+        // md5 byte
+        MessageDigest md5;
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("MD5 not supported", e);
+        }
+        md5.reset();
+        byte[] keyBytes = null;
+        try {
+            keyBytes = key.getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException("Unknown string :" + key, e);
+        }
+
+        md5.update(keyBytes);
+        byte[] digest = md5.digest();
+
+        // hash code, Truncate to 32-bits
+        long hashCode = ((long) (digest[3] & 0xFF) << 24)
+                | ((long) (digest[2] & 0xFF) << 16)
+                | ((long) (digest[1] & 0xFF) << 8)
+                | (digest[0] & 0xFF);
+
+        long truncateHashCode = hashCode & 0xffffffffL;
+        return truncateHashCode;
+    }
+
+}

+ 17 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteFirst.java

@@ -0,0 +1,17 @@
+package com.xxl.job.admin.core.route.strategy;
+
+import com.xxl.job.admin.core.route.ExecutorRouter;
+
+import java.util.ArrayList;
+
+/**
+ * Created by xuxueli on 17/3/10.
+ */
+public class ExecutorRouteFirst extends ExecutorRouter {
+
+    @Override
+    public String route(int jobId, ArrayList<String> addressList) {
+        return addressList.get(0);
+    }
+
+}

+ 17 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteLast.java

@@ -0,0 +1,17 @@
+package com.xxl.job.admin.core.route.strategy;
+
+import com.xxl.job.admin.core.route.ExecutorRouter;
+
+import java.util.ArrayList;
+
+/**
+ * Created by xuxueli on 17/3/10.
+ */
+public class ExecutorRouteLast extends ExecutorRouter {
+
+    @Override
+    public String route(int jobId, ArrayList<String> addressList) {
+        return addressList.get(addressList.size()-1);
+    }
+
+}

+ 20 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteRandom.java

@@ -0,0 +1,20 @@
+package com.xxl.job.admin.core.route.strategy;
+
+import com.xxl.job.admin.core.route.ExecutorRouter;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+/**
+ * Created by xuxueli on 17/3/10.
+ */
+public class ExecutorRouteRandom extends ExecutorRouter {
+
+    private static Random localRandom = new Random();
+
+    @Override
+    public String route(int jobId, ArrayList<String> addressList) {
+        return addressList.get(localRandom.nextInt(addressList.size()));
+    }
+
+}

+ 26 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteRound.java

@@ -0,0 +1,26 @@
+package com.xxl.job.admin.core.route.strategy;
+
+import com.xxl.job.admin.core.route.ExecutorRouter;
+
+import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Created by xuxueli on 17/3/10.
+ */
+public class ExecutorRouteRound extends ExecutorRouter {
+
+    private static ConcurrentHashMap<Integer, Integer> routeCountEachJob = new ConcurrentHashMap<Integer, Integer>();
+    private static int count(int jobId) {
+        Integer count = routeCountEachJob.get(jobId);
+        count = (count==null)?0:++count;
+        routeCountEachJob.put(jobId, count);
+        return count;
+    }
+
+    @Override
+    public String route(int jobId, ArrayList<String> addressList) {
+        return addressList.get(count(jobId)%addressList.size());
+    }
+
+}

+ 5 - 0
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml

@@ -17,6 +17,7 @@
 	    <result column="author" property="author" />
 	    <result column="author" property="author" />
 	    <result column="alarm_email" property="alarmEmail" />
 	    <result column="alarm_email" property="alarmEmail" />
 
 
+		<result column="executor_route_strategy" property="executorRouteStrategy" />
 		<result column="executor_handler" property="executorHandler" />
 		<result column="executor_handler" property="executorHandler" />
 	    <result column="executor_param" property="executorParam" />
 	    <result column="executor_param" property="executorParam" />
 	    
 	    
@@ -37,6 +38,7 @@
 		t.update_time,
 		t.update_time,
 		t.author,
 		t.author,
 		t.alarm_email,
 		t.alarm_email,
+		t.executor_route_strategy,
 		t.executor_handler,
 		t.executor_handler,
 		t.executor_param,
 		t.executor_param,
 		t.glue_switch,
 		t.glue_switch,
@@ -83,6 +85,7 @@
 			update_time,
 			update_time,
 			author,
 			author,
 			alarm_email,
 			alarm_email,
+            executor_route_strategy,
 			executor_handler,
 			executor_handler,
 			executor_param,
 			executor_param,
 			glue_switch,
 			glue_switch,
@@ -98,6 +101,7 @@
 			NOW(),
 			NOW(),
 			#{author},
 			#{author},
 			#{alarmEmail},
 			#{alarmEmail},
+			#{executorRouteStrategy},
 			#{executorHandler},
 			#{executorHandler},
 			#{executorParam},
 			#{executorParam},
 			#{glueSwitch},
 			#{glueSwitch},
@@ -125,6 +129,7 @@
 			update_time = NOW(),
 			update_time = NOW(),
 			author = #{author},
 			author = #{author},
 			alarm_email = #{alarmEmail},
 			alarm_email = #{alarmEmail},
+			executor_route_strategy = #{executorRouteStrategy},
 			executor_handler = #{executorHandler},
 			executor_handler = #{executorHandler},
 			executor_param = #{executorParam},
 			executor_param = #{executorParam},
 			glue_switch = #{glueSwitch},
 			glue_switch = #{glueSwitch},