任务超时控制:支持设置任务超时时间,任务运行超时的情况下,将会主动中断任务;

pull/MERGE
xuxueli 7 years ago
parent 9de5da098b
commit 7687f3fc23

@ -54,23 +54,25 @@ XXL-JOB是一个轻量级分布式任务调度框架其核心设计目标是
- 9、失败处理策略调度失败时的处理策略策略包括失败告警默认、失败重试 - 9、失败处理策略调度失败时的处理策略策略包括失败告警默认、失败重试
- 10、失败重试调度中心调度失败且启用"失败重试"策略时,将会自动重试一次;执行器执行失败且回调失败重试状态时,也将会自动重试一次; - 10、失败重试调度中心调度失败且启用"失败重试"策略时,将会自动重试一次;执行器执行失败且回调失败重试状态时,也将会自动重试一次;
- 11、阻塞处理策略调度过于密集执行器来不及处理时的处理策略策略包括单机串行默认、丢弃后续调度、覆盖之前调度 - 11、阻塞处理策略调度过于密集执行器来不及处理时的处理策略策略包括单机串行默认、丢弃后续调度、覆盖之前调度
- 12、分片广播任务执行器集群部署时任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务; - 12、任务超时控制支持设置任务超时时间任务运行超时的情况下将会主动中断任务
- 13、动态分片分片广播任务以执行器为维度进行分片支持动态扩容执行器集群从而动态增加分片数量协同进行业务处理在进行大数据量业务操作时可显著提升任务处理能力和速度。 - 13、分片广播任务执行器集群部署时任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务;
- 14、事件触发除了"Cron方式"和"任务依赖方式"触发任务执行之外支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务可根据业务事件灵活触发。 - 14、动态分片分片广播任务以执行器为维度进行分片支持动态扩容执行器集群从而动态增加分片数量协同进行业务处理在进行大数据量业务操作时可显著提升任务处理能力和速度。
- 15、任务进度监控支持实时监控任务进度 - 15、事件触发除了"Cron方式"和"任务依赖方式"触发任务执行之外支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务可根据业务事件灵活触发。
- 16、Rolling实时日志支持在线查看调度结果并且支持以Rolling方式实时查看执行器输出的完整的执行日志 - 16、任务进度监控支持实时监控任务进度
- 17、GLUE提供Web IDE支持在线开发任务逻辑代码动态发布实时编译生效省略部署上线的过程。支持30个版本的历史版本回溯。 - 17、Rolling实时日志支持在线查看调度结果并且支持以Rolling方式实时查看执行器输出的完整的执行日志
- 18、脚本任务支持以GLUE模式开发和运行脚本任务包括Shell、Python、NodeJS等类型脚本; - 18、GLUE提供Web IDE支持在线开发任务逻辑代码动态发布实时编译生效省略部署上线的过程。支持30个版本的历史版本回溯。
- 19、任务依赖支持配置子任务依赖当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔; - 19、脚本任务支持以GLUE模式开发和运行脚本任务包括Shell、Python、NodeJS等类型脚本;
- 20、一致性“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行; - 20、任务依赖支持配置子任务依赖当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
- 21、自定义任务参数支持在线配置调度任务入参即时生效 - 21、一致性“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
- 22、调度线程池调度系统多线程触发调度运行确保调度精确执行不被堵塞 - 22、自定义任务参数支持在线配置调度任务入参即时生效
- 23、数据加密调度中心和执行器之间的通讯进行数据加密提升调度信息安全性 - 23、调度线程池调度系统多线程触发调度运行确保调度精确执行不被堵塞
- 24、邮件报警任务失败时支持邮件报警支持配置多邮件地址群发报警邮件 - 24、数据加密调度中心和执行器之间的通讯进行数据加密提升调度信息安全性
- 25、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用; - 25、邮件报警任务失败时支持邮件报警支持配置多邮件地址群发报警邮件
- 26、运行报表支持实时查看运行数据如任务数量、调度次数、执行器数量等以及调度报表如调度日期分布图调度成功分布图等 - 26、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;
- 27、全异步系统底层实现全部异步化针对密集调度进行流量削峰理论上支持任意时长任务的运行 - 27、运行报表支持实时查看运行数据如任务数量、调度次数、执行器数量等以及调度报表如调度日期分布图调度成功分布图等
- 28、国际化调度中心支持国际化设置提供中文、英文两种可选语言默认为中文 - 28、全异步系统底层实现全部异步化针对密集调度进行流量削峰理论上支持任意时长任务的运行
- 29、国际化调度中心支持国际化设置提供中文、英文两种可选语言默认为中文
## Development ## Development
于2015年中我在github上创建XXL-JOB项目仓库并提交第一个commit随之进行系统结构设计UI选型交互设计…… 于2015年中我在github上创建XXL-JOB项目仓库并提交第一个commit随之进行系统结构设计UI选型交互设计……

@ -25,23 +25,25 @@ XXL-JOB是一个轻量级分布式任务调度框架其核心设计目标是
- 9、失败处理策略调度失败时的处理策略策略包括失败告警默认、失败重试 - 9、失败处理策略调度失败时的处理策略策略包括失败告警默认、失败重试
- 10、失败重试调度中心调度失败且启用"失败重试"策略时,将会自动重试一次;执行器执行失败且回调失败重试状态时,也将会自动重试一次; - 10、失败重试调度中心调度失败且启用"失败重试"策略时,将会自动重试一次;执行器执行失败且回调失败重试状态时,也将会自动重试一次;
- 11、阻塞处理策略调度过于密集执行器来不及处理时的处理策略策略包括单机串行默认、丢弃后续调度、覆盖之前调度 - 11、阻塞处理策略调度过于密集执行器来不及处理时的处理策略策略包括单机串行默认、丢弃后续调度、覆盖之前调度
- 12、分片广播任务执行器集群部署时任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务; - 12、任务超时控制支持设置任务超时时间任务运行超时的情况下将会主动中断任务
- 13、动态分片分片广播任务以执行器为维度进行分片支持动态扩容执行器集群从而动态增加分片数量协同进行业务处理在进行大数据量业务操作时可显著提升任务处理能力和速度。 - 13、分片广播任务执行器集群部署时任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务;
- 14、事件触发除了"Cron方式"和"任务依赖方式"触发任务执行之外支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务可根据业务事件灵活触发。 - 14、动态分片分片广播任务以执行器为维度进行分片支持动态扩容执行器集群从而动态增加分片数量协同进行业务处理在进行大数据量业务操作时可显著提升任务处理能力和速度。
- 15、任务进度监控支持实时监控任务进度 - 15、事件触发除了"Cron方式"和"任务依赖方式"触发任务执行之外支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务可根据业务事件灵活触发。
- 16、Rolling实时日志支持在线查看调度结果并且支持以Rolling方式实时查看执行器输出的完整的执行日志 - 16、任务进度监控支持实时监控任务进度
- 17、GLUE提供Web IDE支持在线开发任务逻辑代码动态发布实时编译生效省略部署上线的过程。支持30个版本的历史版本回溯。 - 17、Rolling实时日志支持在线查看调度结果并且支持以Rolling方式实时查看执行器输出的完整的执行日志
- 18、脚本任务支持以GLUE模式开发和运行脚本任务包括Shell、Python、NodeJS等类型脚本; - 18、GLUE提供Web IDE支持在线开发任务逻辑代码动态发布实时编译生效省略部署上线的过程。支持30个版本的历史版本回溯。
- 19、任务依赖支持配置子任务依赖当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔; - 19、脚本任务支持以GLUE模式开发和运行脚本任务包括Shell、Python、NodeJS等类型脚本;
- 20、一致性“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行; - 20、任务依赖支持配置子任务依赖当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
- 21、自定义任务参数支持在线配置调度任务入参即时生效 - 21、一致性“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
- 22、调度线程池调度系统多线程触发调度运行确保调度精确执行不被堵塞 - 22、自定义任务参数支持在线配置调度任务入参即时生效
- 23、数据加密调度中心和执行器之间的通讯进行数据加密提升调度信息安全性 - 23、调度线程池调度系统多线程触发调度运行确保调度精确执行不被堵塞
- 24、邮件报警任务失败时支持邮件报警支持配置多邮件地址群发报警邮件 - 24、数据加密调度中心和执行器之间的通讯进行数据加密提升调度信息安全性
- 25、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用; - 25、邮件报警任务失败时支持邮件报警支持配置多邮件地址群发报警邮件
- 26、运行报表支持实时查看运行数据如任务数量、调度次数、执行器数量等以及调度报表如调度日期分布图调度成功分布图等 - 26、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;
- 27、全异步系统底层实现全部异步化针对密集调度进行流量削峰理论上支持任意时长任务的运行 - 27、运行报表支持实时查看运行数据如任务数量、调度次数、执行器数量等以及调度报表如调度日期分布图调度成功分布图等
- 28、国际化调度中心支持国际化设置提供中文、英文两种可选语言默认为中文 - 28、全异步系统底层实现全部异步化针对密集调度进行流量削峰理论上支持任意时长任务的运行
- 29、国际化调度中心支持国际化设置提供中文、英文两种可选语言默认为中文
### 1.3 发展 ### 1.3 发展
于2015年中我在github上创建XXL-JOB项目仓库并提交第一个commit随之进行系统结构设计UI选型交互设计…… 于2015年中我在github上创建XXL-JOB项目仓库并提交第一个commit随之进行系统结构设计UI选型交互设计……
@ -948,6 +950,11 @@ echo "分片总数 total = $3"
失败 | IJobHandler.FAIL | -1其他 失败 | IJobHandler.FAIL | -1其他
失败重试 | IJobHandler.FAIL_RETRY | 101 失败重试 | IJobHandler.FAIL_RETRY | 101
### 5.16 任务超时控制
支持设置任务超时时间,任务运行超时的情况下,将会主动中断任务;
需要注意的是任务超时中断时与任务终止机制可查看“4.8 终止运行中的任务”)类似,也是通过 "interrupt" 中断任务,因此业务代码需要将 "InterruptedException" 外抛,否则功能不可用。
## 六、版本更新日志 ## 六、版本更新日志
### 6.1 版本 V1.1.x新特性[2015-12-05] ### 6.1 版本 V1.1.x新特性[2015-12-05]
@ -1209,7 +1216,7 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
### 6.22 版本 V1.9.2 特性[迭代中] ### 6.22 版本 V1.9.2 特性[迭代中]
- 1、[迭代中]支持通过API服务操作任务信息 - 1、[迭代中]支持通过API服务操作任务信息
- 2、[迭代中]任务告警逻辑调整任务调度以及任务回调失败时均推送监控队列。后期考虑通过任务Log字段控制告警状态 - 2、[迭代中]任务告警逻辑调整任务调度以及任务回调失败时均推送监控队列。后期考虑通过任务Log字段控制告警状态
- 3、[迭代中]任务超时设置,超时任务主动终止 - 3、任务超时控制:支持设置任务超时时间,任务运行超时的情况下,将会主动中断任务
- 4、任务属性枚举 "任务模式、阻塞策略" 国际化优化; - 4、任务属性枚举 "任务模式、阻塞策略" 国际化优化;
- 5、任务日志表状态字段类型优化 - 5、任务日志表状态字段类型优化
- 6、Glue(Shell) 等脚本任务支持失败重试; - 6、Glue(Shell) 等脚本任务支持失败重试;

@ -158,12 +158,12 @@ 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 '报警邮件',
`execute_timeout` int(11) NOT NULL DEFAULT 0 COMMENT '任务执行超时时间',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略', `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler', `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数', `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略', `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_fail_strategy` varchar(50) DEFAULT NULL COMMENT '失败处理策略', `executor_fail_strategy` varchar(50) DEFAULT NULL COMMENT '失败处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT 0 COMMENT '任务执行超时时间,单位秒',
`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型', `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
`glue_source` text COMMENT 'GLUE源代码', `glue_source` text COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注', `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',

@ -4,6 +4,7 @@ import java.util.Date;
/** /**
* xxl-job info * xxl-job info
*
* @author xuxueli 2016-1-12 18:25:49 * @author xuxueli 2016-1-12 18:25:49
*/ */
public class XxlJobInfo { public class XxlJobInfo {
@ -25,6 +26,7 @@ public class XxlJobInfo {
private String executorParam; // 执行器,任务参数 private String executorParam; // 执行器,任务参数
private String executorBlockStrategy; // 阻塞处理策略 private String executorBlockStrategy; // 阻塞处理策略
private String executorFailStrategy; // 失败处理策略 private String executorFailStrategy; // 失败处理策略
private int executorTimeout; // 任务执行超时时间,单位秒
private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum
private String glueSource; // GLUE源代码 private String glueSource; // GLUE源代码
@ -36,16 +38,6 @@ public class XxlJobInfo {
// copy from quartz // copy from quartz
private String jobStatus; // 任务状态 【base on quartz】 private String jobStatus; // 任务状态 【base on quartz】
private int executeTimeout; // 任务最多执行时间,超时后报警
public int getExecuteTimeout() {
return executeTimeout;
}
public void setExecuteTimeout(int executeTimeout) {
this.executeTimeout = executeTimeout;
}
public int getId() { public int getId() {
return id; return id;
@ -111,15 +103,15 @@ public class XxlJobInfo {
this.alarmEmail = alarmEmail; this.alarmEmail = alarmEmail;
} }
public String getExecutorRouteStrategy() { public String getExecutorRouteStrategy() {
return executorRouteStrategy; return executorRouteStrategy;
} }
public void setExecutorRouteStrategy(String executorRouteStrategy) { public void setExecutorRouteStrategy(String executorRouteStrategy) {
this.executorRouteStrategy = executorRouteStrategy; this.executorRouteStrategy = executorRouteStrategy;
} }
public String getExecutorHandler() { public String getExecutorHandler() {
return executorHandler; return executorHandler;
} }
@ -151,6 +143,14 @@ public class XxlJobInfo {
this.executorFailStrategy = executorFailStrategy; this.executorFailStrategy = executorFailStrategy;
} }
public int getExecutorTimeout() {
return executorTimeout;
}
public void setExecutorTimeout(int executorTimeout) {
this.executorTimeout = executorTimeout;
}
public String getGlueType() { public String getGlueType() {
return glueType; return glueType;
} }

@ -75,6 +75,7 @@ public class XxlJobTrigger {
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorRouteStrategy")).append("").append(executorRouteStrategyEnum.getTitle()).append("("+i+"/"+addressList.size()+")"); // update01 triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorRouteStrategy")).append("").append(executorRouteStrategyEnum.getTitle()).append("("+i+"/"+addressList.size()+")"); // update01
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorBlockStrategy")).append("").append(blockStrategy.getTitle()); triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorBlockStrategy")).append("").append(blockStrategy.getTitle());
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorFailStrategy")).append("").append(failStrategy.getTitle()); triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorFailStrategy")).append("").append(failStrategy.getTitle());
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_timeout")).append("").append(jobInfo.getExecutorTimeout());
// 3、trigger-valid // 3、trigger-valid
if (triggerResult.getCode()==ReturnT.SUCCESS_CODE && CollectionUtils.isEmpty(addressList)) { if (triggerResult.getCode()==ReturnT.SUCCESS_CODE && CollectionUtils.isEmpty(addressList)) {
@ -89,6 +90,7 @@ public class XxlJobTrigger {
triggerParam.setExecutorHandler(jobInfo.getExecutorHandler()); triggerParam.setExecutorHandler(jobInfo.getExecutorHandler());
triggerParam.setExecutorParams(jobInfo.getExecutorParam()); triggerParam.setExecutorParams(jobInfo.getExecutorParam());
triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy()); triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
triggerParam.setExecutorTimeout(jobInfo.getExecutorTimeout());
triggerParam.setLogId(jobLog.getId()); triggerParam.setLogId(jobLog.getId());
triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime()); triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime());
triggerParam.setGlueType(jobInfo.getGlueType()); triggerParam.setGlueType(jobInfo.getGlueType());
@ -96,8 +98,6 @@ public class XxlJobTrigger {
triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime()); triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
triggerParam.setBroadcastIndex(i); triggerParam.setBroadcastIndex(i);
triggerParam.setBroadcastTotal(addressList.size()); // update02 triggerParam.setBroadcastTotal(addressList.size()); // update02
// 执行超时时间
triggerParam.setExecuteTimeout(jobInfo.getExecuteTimeout());
// 4.2、trigger-run (route run / trigger remote executor) // 4.2、trigger-run (route run / trigger remote executor)
triggerResult = runExecutor(triggerParam, address); // update03 triggerResult = runExecutor(triggerParam, address); // update03
@ -145,6 +145,7 @@ public class XxlJobTrigger {
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorRouteStrategy")).append("").append(executorRouteStrategyEnum.getTitle()); triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorRouteStrategy")).append("").append(executorRouteStrategyEnum.getTitle());
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorBlockStrategy")).append("").append(blockStrategy.getTitle()); triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorBlockStrategy")).append("").append(blockStrategy.getTitle());
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorFailStrategy")).append("").append(failStrategy.getTitle()); triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorFailStrategy")).append("").append(failStrategy.getTitle());
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_timeout")).append("").append(jobInfo.getExecutorTimeout());
// 3、trigger-valid // 3、trigger-valid
if (triggerResult.getCode()==ReturnT.SUCCESS_CODE && CollectionUtils.isEmpty(addressList)) { if (triggerResult.getCode()==ReturnT.SUCCESS_CODE && CollectionUtils.isEmpty(addressList)) {
@ -159,6 +160,7 @@ public class XxlJobTrigger {
triggerParam.setExecutorHandler(jobInfo.getExecutorHandler()); triggerParam.setExecutorHandler(jobInfo.getExecutorHandler());
triggerParam.setExecutorParams(jobInfo.getExecutorParam()); triggerParam.setExecutorParams(jobInfo.getExecutorParam());
triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy()); triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
triggerParam.setExecutorTimeout(jobInfo.getExecutorTimeout());
triggerParam.setLogId(jobLog.getId()); triggerParam.setLogId(jobLog.getId());
triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime()); triggerParam.setLogDateTim(jobLog.getTriggerTime().getTime());
triggerParam.setGlueType(jobInfo.getGlueType()); triggerParam.setGlueType(jobInfo.getGlueType());
@ -166,7 +168,6 @@ public class XxlJobTrigger {
triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime()); triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
triggerParam.setBroadcastIndex(0); triggerParam.setBroadcastIndex(0);
triggerParam.setBroadcastTotal(1); triggerParam.setBroadcastTotal(1);
triggerParam.setExecuteTimeout(jobInfo.getExecuteTimeout());
// 4.2、trigger-run (route run / trigger remote executor) // 4.2、trigger-run (route run / trigger remote executor)
triggerResult = executorRouteStrategyEnum.getRouter().routeRun(triggerParam, addressList); triggerResult = executorRouteStrategyEnum.getRouter().routeRun(triggerParam, addressList);

@ -208,6 +208,7 @@ public class XxlJobServiceImpl implements XxlJobService {
exists_jobInfo.setExecutorParam(jobInfo.getExecutorParam()); exists_jobInfo.setExecutorParam(jobInfo.getExecutorParam());
exists_jobInfo.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy()); exists_jobInfo.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
exists_jobInfo.setExecutorFailStrategy(jobInfo.getExecutorFailStrategy()); exists_jobInfo.setExecutorFailStrategy(jobInfo.getExecutorFailStrategy());
exists_jobInfo.setExecutorTimeout(jobInfo.getExecutorTimeout());
exists_jobInfo.setChildJobId(jobInfo.getChildJobId()); exists_jobInfo.setChildJobId(jobInfo.getChildJobId());
xxlJobInfoDao.update(exists_jobInfo); xxlJobInfoDao.update(exists_jobInfo);

@ -30,6 +30,7 @@ system_opt_del=删除
system_unvalid=非法 system_unvalid=非法
system_not_found=不存在 system_not_found=不存在
system_nav=导航 system_nav=导航
system_digits=整数
## daterangepicker ## daterangepicker
daterangepicker_ranges_recent_hour=最近一小时 daterangepicker_ranges_recent_hour=最近一小时
@ -107,7 +108,7 @@ jobinfo_field_gluetype=运行模式
jobinfo_field_executorparam=任务参数 jobinfo_field_executorparam=任务参数
jobinfo_field_cron_unvalid=Cron格式非法 jobinfo_field_cron_unvalid=Cron格式非法
jobinfo_field_author=负责人 jobinfo_field_author=负责人
jobinfo_field_timeout=最大执行时间 jobinfo_field_timeout=任务超时时间
jobinfo_field_alarmemail=报警邮件 jobinfo_field_alarmemail=报警邮件
jobinfo_field_alarmemail_placeholder=请输入报警邮件,多个邮件地址则逗号分隔 jobinfo_field_alarmemail_placeholder=请输入报警邮件,多个邮件地址则逗号分隔
jobinfo_field_executorRouteStrategy=路由策略 jobinfo_field_executorRouteStrategy=路由策略
@ -158,7 +159,7 @@ joblog_clean_type_9=清理所有日志数据
joblog_clean_type_unvalid=清理类型参数异常 joblog_clean_type_unvalid=清理类型参数异常
joblog_handleCode_200=成功 joblog_handleCode_200=成功
joblog_handleCode_500=失败 joblog_handleCode_500=失败
joblog_handleCode_400=超时 joblog_handleCode_502=超时
joblog_handleCode_501=失败重试 joblog_handleCode_501=失败重试
joblog_kill_log=终止任务 joblog_kill_log=终止任务
joblog_kill_log_limit=调度失败,无法终止日志 joblog_kill_log_limit=调度失败,无法终止日志

@ -30,6 +30,7 @@ system_opt_del=Delete
system_unvalid=illegal system_unvalid=illegal
system_not_found=not exist system_not_found=not exist
system_nav=Navigation system_nav=Navigation
system_digits=digits
## daterangepicker ## daterangepicker
daterangepicker_ranges_recent_hour=recent one hour daterangepicker_ranges_recent_hour=recent one hour
@ -103,7 +104,7 @@ jobinfo_field_update=Edit Job
jobinfo_field_id=Job ID jobinfo_field_id=Job ID
jobinfo_field_jobgroup=Executor jobinfo_field_jobgroup=Executor
jobinfo_field_jobdesc=Job description jobinfo_field_jobdesc=Job description
jobinfo_field_timeout=Max execute time jobinfo_field_timeout=Job timeout period
jobinfo_field_gluetype=GLUE Type jobinfo_field_gluetype=GLUE Type
jobinfo_field_executorparam=Param jobinfo_field_executorparam=Param
jobinfo_field_cron_unvalid=The Cron is illegal jobinfo_field_cron_unvalid=The Cron is illegal
@ -158,7 +159,7 @@ joblog_clean_type_9=Clean up all log data
joblog_clean_type_unvalid=Clean type is illegal joblog_clean_type_unvalid=Clean type is illegal
joblog_handleCode_200=Success joblog_handleCode_200=Success
joblog_handleCode_500=Fail joblog_handleCode_500=Fail
joblog_handleCode_400=Timeout joblog_handleCode_502=Timeout
joblog_handleCode_501=Fail retry joblog_handleCode_501=Fail retry
joblog_kill_log=Kill Job joblog_kill_log=Kill Job
joblog_kill_log_limit=Trigger Fail, can not kill job joblog_kill_log_limit=Trigger Fail, can not kill job

@ -21,12 +21,12 @@
<result column="executor_param" property="executorParam" /> <result column="executor_param" property="executorParam" />
<result column="executor_block_strategy" property="executorBlockStrategy" /> <result column="executor_block_strategy" property="executorBlockStrategy" />
<result column="executor_fail_strategy" property="executorFailStrategy" /> <result column="executor_fail_strategy" property="executorFailStrategy" />
<result column="executor_timeout" property="executorTimeout" />
<result column="glue_type" property="glueType" /> <result column="glue_type" property="glueType" />
<result column="glue_source" property="glueSource" /> <result column="glue_source" property="glueSource" />
<result column="glue_remark" property="glueRemark" /> <result column="glue_remark" property="glueRemark" />
<result column="glue_updatetime" property="glueUpdatetime" /> <result column="glue_updatetime" property="glueUpdatetime" />
<result column="execute_timeout" property="executeTimeout" />
<result column="child_jobid" property="childJobId" /> <result column="child_jobid" property="childJobId" />
</resultMap> </resultMap>
@ -45,11 +45,11 @@
t.executor_param, t.executor_param,
t.executor_block_strategy, t.executor_block_strategy,
t.executor_fail_strategy, t.executor_fail_strategy,
t.executor_timeout,
t.glue_type, t.glue_type,
t.glue_source, t.glue_source,
t.glue_remark, t.glue_remark,
t.glue_updatetime, t.glue_updatetime,
t.execute_timeout,
t.child_jobid t.child_jobid
</sql> </sql>
@ -101,12 +101,12 @@
executor_param, executor_param,
executor_block_strategy, executor_block_strategy,
executor_fail_strategy, executor_fail_strategy,
executor_timeout,
glue_type, glue_type,
glue_source, glue_source,
glue_remark, glue_remark,
glue_updatetime, glue_updatetime,
child_jobid, child_jobid
execute_timeout
) VALUES ( ) VALUES (
#{jobGroup}, #{jobGroup},
#{jobCron}, #{jobCron},
@ -120,12 +120,12 @@
#{executorParam}, #{executorParam},
#{executorBlockStrategy}, #{executorBlockStrategy},
#{executorFailStrategy}, #{executorFailStrategy},
#{executorTimeout},
#{glueType}, #{glueType},
#{glueSource}, #{glueSource},
#{glueRemark}, #{glueRemark},
NOW(), NOW(),
#{childJobId}, #{childJobId}
#{executeTimeout}
); );
<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> <!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID() SELECT LAST_INSERT_ID()
@ -152,12 +152,12 @@
executor_param = #{executorParam}, executor_param = #{executorParam},
executor_block_strategy = #{executorBlockStrategy}, executor_block_strategy = #{executorBlockStrategy},
executor_fail_strategy = #{executorFailStrategy}, executor_fail_strategy = #{executorFailStrategy},
executor_timeout = ${executorTimeout},
glue_type = #{glueType}, glue_type = #{glueType},
glue_source = #{glueSource}, glue_source = #{glueSource},
glue_remark = #{glueRemark}, glue_remark = #{glueRemark},
glue_updatetime = #{glueUpdatetime}, glue_updatetime = #{glueUpdatetime},
child_jobid = #{childJobId}, child_jobid = #{childJobId}
execute_timeout = ${executeTimeout}
WHERE id = #{id} WHERE id = #{id}
</update> </update>

@ -170,8 +170,8 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_timeout}<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_timeout}<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="executeTimeout" placeholder="0" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="executorTimeout" placeholder="任务超时时间,单位秒,大于零时生效" maxlength="6" ></div>
</div> </div>
<hr> <hr>
@ -342,6 +342,11 @@ process.exit(0)
<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="${I18n.jobinfo_field_alarmemail_placeholder}" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="${I18n.jobinfo_field_alarmemail_placeholder}" maxlength="100" ></div>
</div> </div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_field_timeout}<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="executorTimeout" placeholder="任务超时时间,单位秒,大于零时生效" maxlength="6" ></div>
</div>
<hr> <hr>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-3 col-sm-6"> <div class="col-sm-offset-3 col-sm-6">

@ -264,7 +264,10 @@ $(function() {
}, },
author : { author : {
required : true required : true
} },
executorTimeout : {
digits:true
}
}, },
messages : { messages : {
jobDesc : { jobDesc : {
@ -288,6 +291,14 @@ $(function() {
element.parent('div').append(error); element.parent('div').append(error);
}, },
submitHandler : function(form) { submitHandler : function(form) {
// process
var executorTimeout = $("#addModal .form input[name='executorTimeout']").val();
if(!/^\d+$/.test(executorTimeout)) {
executorTimeout = 0;
}
$("#addModal .form input[name='executorTimeout']").val(executorTimeout);
$.post(base_url + "/jobinfo/add", $("#addModal .form").serialize(), function(data, status) { $.post(base_url + "/jobinfo/add", $("#addModal .form").serialize(), function(data, status) {
if (data.code == "200") { if (data.code == "200") {
$('#addModal').modal('hide'); $('#addModal').modal('hide');
@ -362,7 +373,7 @@ $(function() {
$("#updateModal .form input[name='jobCron']").val( row.jobCron ); $("#updateModal .form input[name='jobCron']").val( row.jobCron );
$("#updateModal .form input[name='author']").val( row.author ); $("#updateModal .form input[name='author']").val( row.author );
$("#updateModal .form input[name='alarmEmail']").val( row.alarmEmail ); $("#updateModal .form input[name='alarmEmail']").val( row.alarmEmail );
$("#updateModal .form input[name='executeTimeout']").val( row.executeTimeout ); $("#updateModal .form input[name='executorTimeout']").val( row.executorTimeout );
$('#updateModal .form select[name=executorRouteStrategy] option[value='+ row.executorRouteStrategy +']').prop('selected', true); $('#updateModal .form select[name=executorRouteStrategy] option[value='+ row.executorRouteStrategy +']').prop('selected', true);
$("#updateModal .form input[name='executorHandler']").val( row.executorHandler ); $("#updateModal .form input[name='executorHandler']").val( row.executorHandler );
$("#updateModal .form input[name='executorParam']").val( row.executorParam ); $("#updateModal .form input[name='executorParam']").val( row.executorParam );
@ -391,7 +402,10 @@ $(function() {
}, },
author : { author : {
required : true required : true
} },
executorTimeout : {
digits:true
}
}, },
messages : { messages : {
jobDesc : { jobDesc : {
@ -402,7 +416,10 @@ $(function() {
}, },
author : { author : {
required : I18n.system_please_input + I18n.jobinfo_field_author required : I18n.system_please_input + I18n.jobinfo_field_author
} },
executorTimeout : {
digits: I18n.system_please_input + I18n.system_digits
}
}, },
highlight : function(element) { highlight : function(element) {
$(element).closest('.form-group').addClass('has-error'); $(element).closest('.form-group').addClass('has-error');
@ -415,6 +432,14 @@ $(function() {
element.parent('div').append(error); element.parent('div').append(error);
}, },
submitHandler : function(form) { submitHandler : function(form) {
// process
var executorTimeout = $("#updateModal .form input[name='executorTimeout']").val();
if(!/^\d+$/.test(executorTimeout)) {
executorTimeout = 0;
}
$("#updateModal .form input[name='executorTimeout']").val(executorTimeout);
// post // post
$.post(base_url + "/jobinfo/update", $("#updateModal .form").serialize(), function(data, status) { $.post(base_url + "/jobinfo/update", $("#updateModal .form").serialize(), function(data, status) {
if (data.code == "200") { if (data.code == "200") {

@ -159,8 +159,8 @@ $(function() {
html = '<span style="color: red">'+ I18n.joblog_handleCode_500 +'</span>'; html = '<span style="color: red">'+ I18n.joblog_handleCode_500 +'</span>';
} else if (data == 501) { } else if (data == 501) {
html = '<span style="color: red">'+ I18n.joblog_handleCode_501 +'</span>'; html = '<span style="color: red">'+ I18n.joblog_handleCode_501 +'</span>';
} else if (data == 400) { } else if (data == 502) {
html = '<span style="color: red">'+ I18n.joblog_handleCode_400 +'</span>'; html = '<span style="color: red">'+ I18n.joblog_handleCode_502 +'</span>';
} else if (data == 0) { } else if (data == 0) {
html = ''; html = '';
} }

@ -12,12 +12,10 @@ public class ReturnT<T> implements Serializable {
public static final int SUCCESS_CODE = 200; public static final int SUCCESS_CODE = 200;
public static final int FAIL_CODE = 500; public static final int FAIL_CODE = 500;
public static final int EXECUTE_TIMEOUT = 400;
public static final ReturnT<String> SUCCESS = new ReturnT<String>(null); public static final ReturnT<String> SUCCESS = new ReturnT<String>(null);
public static final ReturnT<String> FAIL = new ReturnT<String>(FAIL_CODE, null); public static final ReturnT<String> FAIL = new ReturnT<String>(FAIL_CODE, null);
public static final ReturnT<String> TIMEOUT = new ReturnT<String>(EXECUTE_TIMEOUT, "执行超时");
private int code; private int code;
private String msg; private String msg;
private T content; private T content;

@ -13,6 +13,7 @@ public class TriggerParam implements Serializable{
private String executorHandler; private String executorHandler;
private String executorParams; private String executorParams;
private String executorBlockStrategy; private String executorBlockStrategy;
private int executorTimeout;
private int logId; private int logId;
private long logDateTim; private long logDateTim;
@ -24,15 +25,6 @@ public class TriggerParam implements Serializable{
private int broadcastIndex; private int broadcastIndex;
private int broadcastTotal; private int broadcastTotal;
private int executeTimeout;
public int getExecuteTimeout() {
return executeTimeout;
}
public void setExecuteTimeout(int executeTimeout) {
this.executeTimeout = executeTimeout;
}
public int getJobId() { public int getJobId() {
return jobId; return jobId;
@ -66,6 +58,14 @@ public class TriggerParam implements Serializable{
this.executorBlockStrategy = executorBlockStrategy; this.executorBlockStrategy = executorBlockStrategy;
} }
public int getExecutorTimeout() {
return executorTimeout;
}
public void setExecutorTimeout(int executorTimeout) {
this.executorTimeout = executorTimeout;
}
public int getLogId() { public int getLogId() {
return logId; return logId;
} }
@ -122,6 +122,7 @@ public class TriggerParam implements Serializable{
this.broadcastTotal = broadcastTotal; this.broadcastTotal = broadcastTotal;
} }
@Override @Override
public String toString() { public String toString() {
return "TriggerParam{" + return "TriggerParam{" +
@ -129,6 +130,7 @@ public class TriggerParam implements Serializable{
", executorHandler='" + executorHandler + '\'' + ", executorHandler='" + executorHandler + '\'' +
", executorParams='" + executorParams + '\'' + ", executorParams='" + executorParams + '\'' +
", executorBlockStrategy='" + executorBlockStrategy + '\'' + ", executorBlockStrategy='" + executorBlockStrategy + '\'' +
", executorTimeout=" + executorTimeout +
", logId=" + logId + ", logId=" + logId +
", logDateTim=" + logDateTim + ", logDateTim=" + logDateTim +
", glueType='" + glueType + '\'' + ", glueType='" + glueType + '\'' +

@ -14,10 +14,10 @@ public abstract class IJobHandler {
public static final ReturnT<String> SUCCESS = new ReturnT<String>(200, null); public static final ReturnT<String> SUCCESS = new ReturnT<String>(200, null);
/** fail */ /** fail */
public static final ReturnT<String> FAIL = new ReturnT<String>(500, null); public static final ReturnT<String> FAIL = new ReturnT<String>(500, null);
/** timeout */
public static final ReturnT<String> TIMEOUT = new ReturnT<String>(400, null);
/** fail retry */ /** fail retry */
public static final ReturnT<String> FAIL_RETRY = new ReturnT<String>(501, null); public static final ReturnT<String> FAIL_RETRY = new ReturnT<String>(501, null);
/** fail timeout */
public static final ReturnT<String> FAIL_TIMEOUT = new ReturnT<String>(502, null);
/** /**

@ -15,13 +15,9 @@ import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.concurrent.*;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.*;
import java.util.concurrent.TimeUnit;
/** /**
@ -111,7 +107,6 @@ public class JobThread extends Thread{
TriggerParam triggerParam = null; TriggerParam triggerParam = null;
ReturnT<String> executeResult = null; ReturnT<String> executeResult = null;
ExecutorService singleThread = Executors.newSingleThreadExecutor();
try { try {
// to check toStop signal, we need cycle, so wo cannot use queue.take(), instand of poll(timeout) // to check toStop signal, we need cycle, so wo cannot use queue.take(), instand of poll(timeout)
triggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS); triggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS);
@ -127,27 +122,36 @@ public class JobThread extends Thread{
// execute // execute
XxlJobLogger.log("<br>----------- xxl-job job execute start -----------<br>----------- Param:" + triggerParam.getExecutorParams()); XxlJobLogger.log("<br>----------- xxl-job job execute start -----------<br>----------- Param:" + triggerParam.getExecutorParams());
int executeTimeout = triggerParam.getExecuteTimeout();
final TriggerParam finalTriggerParam = triggerParam; if (triggerParam.getExecutorTimeout() > 0) {
// limit timeout
Future<ReturnT<String>> future = singleThread.submit(new Callable<ReturnT<String>>() { Thread futureThread = null;
@Override try {
public ReturnT<String> call() throws Exception { final TriggerParam triggerParamTmp = triggerParam;
return handler.execute(finalTriggerParam.getExecutorParams()); FutureTask<ReturnT<String>> futureTask = new FutureTask<ReturnT<String>>(new Callable<ReturnT<String>>() {
} @Override
}); public ReturnT<String> call() throws Exception {
return handler.execute(triggerParamTmp.getExecutorParams());
try { }
if (executeTimeout > 0) { });
executeResult = future.get(executeTimeout, TimeUnit.SECONDS); futureThread = new Thread(futureTask);
} else { futureThread.start();
executeResult = future.get();
executeResult = futureTask.get(triggerParam.getExecutorTimeout(), TimeUnit.SECONDS);
} catch (TimeoutException e) {
XxlJobLogger.log("<br>----------- xxl-job job execute timeout");
XxlJobLogger.log(e);
executeResult = new ReturnT<String>(IJobHandler.FAIL_TIMEOUT.getCode(), "job execute timeout " + e.getMessage());
} finally {
futureThread.interrupt();
} }
} catch (TimeoutException timeoutException) { } else {
executeResult = ReturnT.TIMEOUT; // just execute
executeResult = handler.execute(triggerParam.getExecutorParams());
} }
if (executeResult == null) { if (executeResult == null) {
executeResult = IJobHandler.FAIL; executeResult = IJobHandler.FAIL;
} }
@ -170,9 +174,6 @@ public class JobThread extends Thread{
XxlJobLogger.log("<br>----------- JobThread Exception:" + errorMsg + "<br>----------- xxl-job job execute end(error) -----------"); XxlJobLogger.log("<br>----------- JobThread Exception:" + errorMsg + "<br>----------- xxl-job job execute end(error) -----------");
} finally { } finally {
if (singleThread != null) {
singleThread.shutdown();
}
if(triggerParam != null) { if(triggerParam != null) {
// callback handler info // callback handler info
if (!toStop) { if (!toStop) {

Loading…
Cancel
Save