diff --git a/README.md b/README.md index 458576d7..66950ab4 100644 --- a/README.md +++ b/README.md @@ -732,12 +732,12 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段 - 8、GLUE依赖注入逻辑优化,支持别名注入; #### 6.11 版本 V1.6.0 特性(CODING) -- 1、通讯:hex 通讯调整为 http-rpc 模式; -- 2、线程模型统一; -- 3、执行器支持手动设置执行地址列表,提供开关切换使用注册地址还是手动设置的地址; -- 4、执行器路由规则:第一个、循环、随机、顺序故障(默认)转移; -- 5、CleanCode,清理无效的历史参数; -- 6、规范系统配置数据,通过配置文件统一管理; +- 1、通讯方案升级,原基于HEX的通讯模型调整为基于HTTP的二进制RPC的通讯模型; +- 2、规范线程模型统一,统一线程销毁方案; +- 3、CleanCode,清理无效的历史参数; +- 4、规范系统配置数据,通过配置文件统一管理; +- 5、执行器支持手动设置执行地址列表,提供开关切换使用注册地址还是手动设置的地址; +- 6、执行器路由规则:第一个、循环、随机、顺序故障(默认)转移; #### TODO LIST - 1、支持脚本JOB(源码或指定路径), 即shell/python/php等, 日志实时输出并支持在线监控;定制JobHandler实现; diff --git a/db/tables_xxl_job.sql b/db/tables_xxl_job.sql index 0e76e0cb..7b34f92a 100644 --- a/db/tables_xxl_job.sql +++ b/db/tables_xxl_job.sql @@ -201,14 +201,17 @@ CREATE TABLE XXL_JOB_QRTZ_TRIGGER_REGISTRY ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE TABLE XXL_JOB_QRTZ_TRIGGER_GROUP ( +CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_GROUP` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `app_name` varchar(64) NOT NULL, - `title` varchar(12) NOT NULL, - `order` tinyint(4) NOT NULL, + `app_name` varchar(64) NOT NULL COMMENT '执行器AppName', + `title` varchar(12) NOT NULL COMMENT '执行器名称', + `order` tinyint(4) NOT NULL DEFAULT '0' COMMENT '排序', + `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入', + `address_list` varchar(200) DEFAULT NULL COMMENT '执行器地址列表,多地址逗号分隔', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -INSERT INTO `XXL_JOB_QRTZ_TRIGGER_GROUP` VALUES ('1', 'xxl-job-executor-example', '示例执行器', '1'); + +INSERT INTO `XXL_JOB_QRTZ_TRIGGER_GROUP` ( `app_name`, `title`, `order`, `address_type`, `address_list`) values ( 'xxl-job-executor-example', '示例执行器', '1', '0', null); commit; diff --git a/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobGroupController.java b/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobGroupController.java index a5c32fed..b5b3524b 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobGroupController.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobGroupController.java @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; +import java.util.Arrays; import java.util.List; /** @@ -40,7 +41,14 @@ public class JobGroupController { if (CollectionUtils.isNotEmpty(list)) { for (XxlJobGroup group: list) { - List registryList = JobRegistryHelper.discover(RegistHelper.RegistType.EXECUTOR.name(), group.getAppName()); + List registryList = null; + if (group.getAddressType() == 0) { + registryList = JobRegistryHelper.discover(RegistHelper.RegistType.EXECUTOR.name(), group.getAppName()); + } else { + if (StringUtils.isNotBlank(group.getAddressList())) { + registryList = Arrays.asList(group.getAddressList().split(",")); + } + } group.setRegistryList(registryList); } } @@ -64,6 +72,17 @@ public class JobGroupController { if (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) { return new ReturnT(500, "请输入名称"); } + if (xxlJobGroup.getAddressType()!=0) { + if (StringUtils.isBlank(xxlJobGroup.getAddressList())) { + return new ReturnT(500, "手动录入注册方式,机器地址不可为空"); + } + String[] addresss = xxlJobGroup.getAddressList().split(","); + for (String item: addresss) { + if (StringUtils.isBlank(item)) { + return new ReturnT(500, "机器地址非法"); + } + } + } int ret = xxlJobGroupDao.save(xxlJobGroup); return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL; @@ -82,6 +101,17 @@ public class JobGroupController { if (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) { return new ReturnT(500, "请输入名称"); } + if (xxlJobGroup.getAddressType()!=0) { + if (StringUtils.isBlank(xxlJobGroup.getAddressList())) { + return new ReturnT(500, "手动录入注册方式,机器地址不可为空"); + } + String[] addresss = xxlJobGroup.getAddressList().split(","); + for (String item: addresss) { + if (StringUtils.isBlank(item)) { + return new ReturnT(500, "机器地址非法"); + } + } + } int ret = xxlJobGroupDao.update(xxlJobGroup); return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL; diff --git a/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobGroup.java b/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobGroup.java index 3b2ae97c..6e6b7add 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobGroup.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobGroup.java @@ -11,9 +11,11 @@ public class XxlJobGroup { private String appName; private String title; private int order; + private int addressType; // 执行器地址类型:0=自动注册、1=手动录入 + private String addressList; // 执行器地址列表,多地址逗号分隔(手动录入) // registry list - private List registryList; + private List registryList; // 执行器地址列表(系统注册) public int getId() { return id; @@ -54,4 +56,20 @@ public class XxlJobGroup { public void setRegistryList(List registryList) { this.registryList = registryList; } + + public int getAddressType() { + return addressType; + } + + public void setAddressType(int addressType) { + this.addressType = addressType; + } + + public String getAddressList() { + return addressList; + } + + public void setAddressList(String addressList) { + this.addressList = addressList; + } } diff --git a/xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobRegistryHelper.java b/xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobRegistryHelper.java index 46b667c8..564f434b 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobRegistryHelper.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobRegistryHelper.java @@ -39,9 +39,11 @@ public class JobRegistryHelper { XxlJobDynamicScheduler.xxlJobRegistryDao.registrySave(RegistHelper.RegistType.ADMIN.name(), RegistHelper.RegistType.ADMIN.name(), XxlJobDynamicScheduler.getCallbackAddress()); } + // remove dead admin/executor + XxlJobDynamicScheduler.xxlJobRegistryDao.removeDead(RegistHelper.TIMEOUT*2); + // fresh registry map ConcurrentHashMap> temp = new ConcurrentHashMap>(); - XxlJobDynamicScheduler.xxlJobRegistryDao.removeDead(RegistHelper.TIMEOUT*2); List list = XxlJobDynamicScheduler.xxlJobRegistryDao.findAll(RegistHelper.TIMEOUT*2); if (list != null) { for (XxlJobRegistry item: list) { diff --git a/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobGroupMapper.xml b/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobGroupMapper.xml index 465eab9e..0cb1efbc 100644 --- a/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobGroupMapper.xml +++ b/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobGroupMapper.xml @@ -8,13 +8,17 @@ + + t.id, t.app_name, t.title, - t.order + t.order, + t.address_type, + t.address_list - INSERT INTO XXL_JOB_QRTZ_TRIGGER_GROUP ( `app_name`, `title`, `order`) - values ( #{appName}, #{title}, #{order}); + INSERT INTO XXL_JOB_QRTZ_TRIGGER_GROUP ( `app_name`, `title`, `order`, `address_type`, `address_list`) + values ( #{appName}, #{title}, #{order}, #{addressType}, #{addressList}); UPDATE XXL_JOB_QRTZ_TRIGGER_GROUP SET `app_name` = #{appName}, `title` = #{title}, - `order` = #{order} + `order` = #{order}, + `address_type` = #{addressType}, + `address_list` = #{addressList} WHERE id = #{id} diff --git a/xxl-job-admin/src/main/webapp/WEB-INF/template/jobgroup/jobgroup.index.ftl b/xxl-job-admin/src/main/webapp/WEB-INF/template/jobgroup/jobgroup.index.ftl index 41533dd0..2b7f6545 100644 --- a/xxl-job-admin/src/main/webapp/WEB-INF/template/jobgroup/jobgroup.index.ftl +++ b/xxl-job-admin/src/main/webapp/WEB-INF/template/jobgroup/jobgroup.index.ftl @@ -33,16 +33,17 @@

执行器列表

        - 调度中心OnLine:<#if adminAddressList?exists><#list adminAddressList as item>${item} + 调度中心OnLine机器:<#if adminAddressList?exists><#list adminAddressList as item>${item}
- + <#----> + - + @@ -51,13 +52,20 @@ <#if list?exists && list?size gt 0> <#list list as group> - + <#----> + - + @@ -93,6 +101,18 @@
+
+ +
+ 自动注册 +      + 手动录入 +
+
+
+ +
+

@@ -127,6 +147,18 @@
+
+ +
+ 自动注册 +      + 手动录入 +
+
+
+ +
+

diff --git a/xxl-job-admin/src/main/webapp/static/js/jobgroup.index.1.js b/xxl-job-admin/src/main/webapp/static/js/jobgroup.index.1.js index 77e6a7e8..92c0402b 100644 --- a/xxl-job-admin/src/main/webapp/static/js/jobgroup.index.1.js +++ b/xxl-job-admin/src/main/webapp/static/js/jobgroup.index.1.js @@ -107,12 +107,33 @@ $(function() { $("#addModal .form .form-group").removeClass("has-error"); }); + // 注册方式,切换 + $("#addModal input[name=addressType], #updateModal input[name=addressType]").click(function(){ + var addressType = $(this).val(); + var $addressList = $(this).parents("form").find("input[name=addressList]"); + if (addressType == 0) { + $addressList.val(""); + $addressList.attr("readonly","readonly"); + } else { + $addressList.removeAttr("readonly"); + } + }); + + // update $('.update').on('click', function(){ $("#updateModal .form input[name='id']").val($(this).attr("id")); $("#updateModal .form input[name='appName']").val($(this).attr("appName")); $("#updateModal .form input[name='title']").val($(this).attr("title")); $("#updateModal .form input[name='order']").val($(this).attr("order")); + // 注册方式 + var addressType = $(this).attr("addressType"); + $("#updateModal .form input[name='addressType']").removeAttr('checked'); + //$("#updateModal .form input[name='addressType'][value='"+ addressType +"']").attr('checked', 'true'); + $("#updateModal .form input[name='addressType'][value='"+ addressType +"']").click(); + // 机器地址 + $("#updateModal .form input[name='addressList']").val($(this).attr("addressList")); + $('#updateModal').modal({backdrop: false, keyboard: false}).modal('show'); }); var updateModalValidate = $("#updateModal .form").validate({ diff --git a/xxl-job-core/src/main/java/com/xxl/job/core/util/IpUtil.java b/xxl-job-core/src/main/java/com/xxl/job/core/util/IpUtil.java index 7fe6d046..c29fb2e2 100644 --- a/xxl-job-core/src/main/java/com/xxl/job/core/util/IpUtil.java +++ b/xxl-job-core/src/main/java/com/xxl/job/core/util/IpUtil.java @@ -16,9 +16,9 @@ import java.util.regex.Pattern; public class IpUtil { private static final Logger logger = LoggerFactory.getLogger(IpUtil.class); - public static final String ANYHOST = "0.0.0.0"; - public static final String LOCALHOST = "127.0.0.1"; - private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); + private static final String ANYHOST = "0.0.0.0"; + private static final String LOCALHOST = "127.0.0.1"; + public static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); private static volatile InetAddress LOCAL_ADDRESS = null;
IDID排序 AppName 名称排序注册方式 OnLine 机器 操作
${group.id}${group.id}${group.order} ${group.appName} ${group.title}${group.order}<#if group.addressType==0>自动注册<#else>手动录入 <#if group.registryList?exists><#list group.registryList as item>${item}
- +