diff --git a/doc/XXL-JOB官方文档.md b/doc/XXL-JOB官方文档.md index 657ab8cd..08919df5 100644 --- a/doc/XXL-JOB官方文档.md +++ b/doc/XXL-JOB官方文档.md @@ -2811,6 +2811,7 @@ public void execute() { - 9、【优化】调度日志调整,完善日志参数信息,合并PR-2761; - 10、【优化】I18N国际化完善,合并PR-2888; - 11、【优化】告警组件初始化重构,提升代码可维护性,合并PR-2903; +- 12、【优化】一致性哈希路由算法优化,重构哈希环逻辑提升代码简洁性; ### 7.45 版本 v3.4.1 Release Notes[ING] - 1、【TODO】调度中心OpenAPI完善,提供任务管理能力;封装Agent Skill并推送ClawHub; diff --git a/xxl-job-admin/src/main/java/com/xxl/job/admin/scheduler/route/strategy/ExecutorRouteConsistentHash.java b/xxl-job-admin/src/main/java/com/xxl/job/admin/scheduler/route/strategy/ExecutorRouteConsistentHash.java index 879fc37b..18dc9345 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/admin/scheduler/route/strategy/ExecutorRouteConsistentHash.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/admin/scheduler/route/strategy/ExecutorRouteConsistentHash.java @@ -8,7 +8,7 @@ import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.List; -import java.util.SortedMap; +import java.util.Map; import java.util.TreeMap; /** @@ -62,9 +62,10 @@ public class ExecutorRouteConsistentHash extends ExecutorRouter { */ public String hashJob(int jobId, List addressList) { + // 1、hash ring // ------A1------A2-------A3------ // -----------J1------------------ - TreeMap addressRing = new TreeMap(); + TreeMap addressRing = new TreeMap<>(); for (String address: addressList) { for (int i = 0; i < VIRTUAL_NODE_NUM; i++) { long addressHash = hash("SHARD-" + address + "-NODE-" + i); @@ -72,11 +73,20 @@ public class ExecutorRouteConsistentHash extends ExecutorRouter { } } + // 2、generate job-hash long jobHash = hash(String.valueOf(jobId)); - SortedMap lastRing = addressRing.tailMap(jobHash); + + // 3、route job-node + Map.Entry ceilingEntry = addressRing.ceilingEntry(jobHash); + if (ceilingEntry != null) { + return ceilingEntry.getValue(); + } + /*SortedMap lastRing = addressRing.tailMap(jobHash); if (!lastRing.isEmpty()) { return lastRing.get(lastRing.firstKey()); - } + }*/ + + // 4、default first node return addressRing.firstEntry().getValue(); } diff --git a/xxl-job-admin/src/test/java/com/xxl/job/admin/schedule/route/ExecutorRouteConsistentHashTest.java b/xxl-job-admin/src/test/java/com/xxl/job/admin/schedule/route/ExecutorRouteConsistentHashTest.java new file mode 100644 index 00000000..16df5846 --- /dev/null +++ b/xxl-job-admin/src/test/java/com/xxl/job/admin/schedule/route/ExecutorRouteConsistentHashTest.java @@ -0,0 +1,25 @@ +package com.xxl.job.admin.schedule.route; + +import com.xxl.job.admin.scheduler.route.strategy.ExecutorRouteConsistentHash; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class ExecutorRouteConsistentHashTest { + private static final Logger logger = LoggerFactory.getLogger(ExecutorRouteConsistentHashTest.class); + + @Test + public void test() { + + List addressList = List.of("192.168.0.1:1111", "192.168.0.2:2222", "192.168.0.3:3333"); + ExecutorRouteConsistentHash executorRouteConsistentHash = new ExecutorRouteConsistentHash(); + + for (int i = 0; i < 100; i++) { + int jobId = 1000 + i; + String address = executorRouteConsistentHash.hashJob(jobId, addressList); + logger.info("jobId:{}, address:{}", jobId, address); + } + } +}