Przeglądaj źródła

命令行任务:原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可;

xuxueli 6 lat temu
rodzic
commit
1427644853

+ 17 - 13
doc/XXL-JOB官方文档.md

@@ -33,17 +33,18 @@ XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是
 - 17、Rolling实时日志:支持在线查看调度结果,并且支持以Rolling方式实时查看执行器输出的完整的执行日志;
 - 18、GLUE:提供Web IDE,支持在线开发任务逻辑代码,动态发布,实时编译生效,省略部署上线的过程。支持30个版本的历史版本回溯。
 - 19、脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python、NodeJS、PHP、PowerShell等类型脚本;
-- 20、任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
-- 21、一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
-- 22、自定义任务参数:支持在线配置调度任务入参,即时生效;
-- 23、调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞;
-- 24、数据加密:调度中心和执行器之间的通讯进行数据加密,提升调度信息安全性;
-- 25、邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;
-- 26、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;
-- 27、运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
-- 28、全异步:任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰,理论上支持任意时长任务的运行;
-- 29、跨平台:原生提供通用HTTP任务Handler(Bean任务,"HttpJobHandler");业务方只需要提供HTTP链接即可,不限制语言、平台;
-- 30、国际化:调度中心支持国际化设置,提供中文、英文两种可选语言,默认为中文;
+- 20、命令行任务:原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可;
+- 21、任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
+- 22、一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
+- 23、自定义任务参数:支持在线配置调度任务入参,即时生效;
+- 24、调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞;
+- 25、数据加密:调度中心和执行器之间的通讯进行数据加密,提升调度信息安全性;
+- 26、邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;
+- 27、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;
+- 28、运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
+- 29、全异步:任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰,理论上支持任意时长任务的运行;
+- 30、跨平台:原生提供通用HTTP任务Handler(Bean任务,"HttpJobHandler");业务方只需要提供HTTP链接即可,不限制语言、平台;
+- 31、国际化:调度中心支持国际化设置,提供中文、英文两种可选语言,默认为中文;
 
 
 ### 1.3 发展
@@ -1017,10 +1018,13 @@ docker build -t xuxueli/xxl-job-admin ./xxl-job-admin
 docker run --name xxl-job-admin -p 8080:8080 -d xuxueli/xxl-job-admin
 ```
 
-### 5.20 避免任务重复执行
+### 5.20 避免任务重复执行   
 调度密集或者耗时任务可能会导致任务阻塞,集群情况下调度组件小概率情况下会重复触发;
 针对上述情况,可以通过结合 "单机路由策略(如:第一台、一致性哈希)" + "阻塞策略(如:单机串行、丢弃后续调度)" 来规避,最终避免任务重复执行。 
 
+### 5.21 命令行任务   
+原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可;
+如任务参数 "pwd" 将会执行命令并输出数据;
 
 
 ## 六、版本更新日志
@@ -1333,7 +1337,7 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
 - 7、任务RollingLog展示逻辑优化,修复超时任务无法查看的问题;
 - 8、任务状态优化,仅运行状态"NORMAL"任务关联至quartz,降低quartz底层数据存储与调度压力;
 - 9、任务状态规范:新增任务默认停止状态,任务更新时保持任务状态不变;
-- 10、[迭代中]原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可,可执行任意命令
+- 10、命令行任务:原生提供通用命令行任务Handler(Bean任务,"CommandJobHandler");业务方只需要提供命令行即可;
 - 11、[迭代中]docker镜像,并且推送docker镜像到中央仓库,更进一步实现产品开箱即用;
 
 

BIN
doc/XXL-JOB架构图.pptx


+ 2 - 0
xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/config/FrameLessXxlJobConfig.java

@@ -1,5 +1,6 @@
 package com.xuxueli.executor.sample.frameless.config;
 
+import com.xuxueli.executor.sample.frameless.jobhandler.CommandJobHandler;
 import com.xuxueli.executor.sample.frameless.jobhandler.DemoJobHandler;
 import com.xuxueli.executor.sample.frameless.jobhandler.HttpJobHandler;
 import com.xuxueli.executor.sample.frameless.jobhandler.ShardingJobHandler;
@@ -35,6 +36,7 @@ public class FrameLessXxlJobConfig {
         XxlJobExecutor.registJobHandler("demoJobHandler", new DemoJobHandler());
         XxlJobExecutor.registJobHandler("shardingJobHandler", new ShardingJobHandler());
         XxlJobExecutor.registJobHandler("httpJobHandler", new HttpJobHandler());
+        XxlJobExecutor.registJobHandler("commandJobHandler", new CommandJobHandler());
 
         // load executor prop
         Properties xxlJobProp = loadProperties("xxl-job-executor.properties");

+ 54 - 0
xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xuxueli/executor/sample/frameless/jobhandler/CommandJobHandler.java

@@ -0,0 +1,54 @@
+package com.xuxueli.executor.sample.frameless.jobhandler;
+
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.IJobHandler;
+import com.xxl.job.core.log.XxlJobLogger;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * 命令行任务
+ *
+ * @author xuxueli 2018-09-16 03:48:34
+ */
+public class CommandJobHandler extends IJobHandler {
+
+    @Override
+    public ReturnT<String> execute(String param) throws Exception {
+        String command = param;
+        int exitValue = -1;
+
+        BufferedReader bufferedReader = null;
+        try {
+            // command process
+            Process process = Runtime.getRuntime().exec(command);
+            BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream());
+            bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream));
+
+            // command log
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                XxlJobLogger.log(line);
+            }
+
+            // command exit
+            process.waitFor();
+            exitValue = process.exitValue();
+        } catch (Exception e) {
+            XxlJobLogger.log(e);
+        } finally {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+        }
+
+        if (exitValue == 0) {
+            return IJobHandler.SUCCESS;
+        } else {
+            return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed");
+        }
+    }
+
+}

+ 2 - 0
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/config/JFinalCoreConfig.java

@@ -4,6 +4,7 @@ import com.jfinal.config.*;
 import com.jfinal.kit.Prop;
 import com.jfinal.kit.PropKit;
 import com.xuxueli.executor.sample.jfinal.controller.IndexController;
+import com.xuxueli.executor.sample.jfinal.jobhandler.CommandJobHandler;
 import com.xuxueli.executor.sample.jfinal.jobhandler.DemoJobHandler;
 import com.xuxueli.executor.sample.jfinal.jobhandler.HttpJobHandler;
 import com.xuxueli.executor.sample.jfinal.jobhandler.ShardingJobHandler;
@@ -25,6 +26,7 @@ public class JFinalCoreConfig extends JFinalConfig {
 		XxlJobExecutor.registJobHandler("demoJobHandler", new DemoJobHandler());
 		XxlJobExecutor.registJobHandler("shardingJobHandler", new ShardingJobHandler());
 		XxlJobExecutor.registJobHandler("httpJobHandler", new HttpJobHandler());
+		XxlJobExecutor.registJobHandler("commandJobHandler", new CommandJobHandler());
 
 		// load executor prop
 		Prop xxlJobProp = PropKit.use("xxl-job-executor.properties");

+ 54 - 0
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/CommandJobHandler.java

@@ -0,0 +1,54 @@
+package com.xuxueli.executor.sample.jfinal.jobhandler;
+
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.IJobHandler;
+import com.xxl.job.core.log.XxlJobLogger;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * 命令行任务
+ *
+ * @author xuxueli 2018-09-16 03:48:34
+ */
+public class CommandJobHandler extends IJobHandler {
+
+    @Override
+    public ReturnT<String> execute(String param) throws Exception {
+        String command = param;
+        int exitValue = -1;
+
+        BufferedReader bufferedReader = null;
+        try {
+            // command process
+            Process process = Runtime.getRuntime().exec(command);
+            BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream());
+            bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream));
+
+            // command log
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                XxlJobLogger.log(line);
+            }
+
+            // command exit
+            process.waitFor();
+            exitValue = process.exitValue();
+        } catch (Exception e) {
+            XxlJobLogger.log(e);
+        } finally {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+        }
+
+        if (exitValue == 0) {
+            return IJobHandler.SUCCESS;
+        } else {
+            return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed");
+        }
+    }
+
+}

+ 58 - 0
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/CommandJobHandler.java

@@ -0,0 +1,58 @@
+package com.xuxueli.executor.sample.nutz.jobhandler;
+
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.IJobHandler;
+import com.xxl.job.core.handler.annotation.JobHandler;
+import com.xxl.job.core.log.XxlJobLogger;
+import org.nutz.ioc.loader.annotation.IocBean;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * 命令行任务
+ *
+ * @author xuxueli 2018-09-16 03:48:34
+ */
+@JobHandler(value="commandJobHandler")
+@IocBean
+public class CommandJobHandler extends IJobHandler {
+
+    @Override
+    public ReturnT<String> execute(String param) throws Exception {
+        String command = param;
+        int exitValue = -1;
+
+        BufferedReader bufferedReader = null;
+        try {
+            // command process
+            Process process = Runtime.getRuntime().exec(command);
+            BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream());
+            bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream));
+
+            // command log
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                XxlJobLogger.log(line);
+            }
+
+            // command exit
+            process.waitFor();
+            exitValue = process.exitValue();
+        } catch (Exception e) {
+            XxlJobLogger.log(e);
+        } finally {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+        }
+
+        if (exitValue == 0) {
+            return IJobHandler.SUCCESS;
+        } else {
+            return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed");
+        }
+    }
+
+}

+ 58 - 0
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/CommandJobHandler.java

@@ -0,0 +1,58 @@
+package com.xxl.job.executor.service.jobhandler;
+
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.IJobHandler;
+import com.xxl.job.core.handler.annotation.JobHandler;
+import com.xxl.job.core.log.XxlJobLogger;
+import org.springframework.stereotype.Component;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * 命令行任务
+ *
+ * @author xuxueli 2018-09-16 03:48:34
+ */
+@JobHandler(value="commandJobHandler")
+@Component
+public class CommandJobHandler extends IJobHandler {
+
+    @Override
+    public ReturnT<String> execute(String param) throws Exception {
+        String command = param;
+        int exitValue = -1;
+
+        BufferedReader bufferedReader = null;
+        try {
+            // command process
+            Process process = Runtime.getRuntime().exec(command);
+            BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream());
+            bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream));
+
+            // command log
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                XxlJobLogger.log(line);
+            }
+
+            // command exit
+            process.waitFor();
+            exitValue = process.exitValue();
+        } catch (Exception e) {
+            XxlJobLogger.log(e);
+        } finally {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+        }
+
+        if (exitValue == 0) {
+            return IJobHandler.SUCCESS;
+        } else {
+            return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed");
+        }
+    }
+
+}

+ 58 - 0
xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/CommandJobHandler.java

@@ -0,0 +1,58 @@
+package com.xxl.job.executor.service.jobhandler;
+
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.IJobHandler;
+import com.xxl.job.core.handler.annotation.JobHandler;
+import com.xxl.job.core.log.XxlJobLogger;
+import org.springframework.stereotype.Component;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * 命令行任务
+ *
+ * @author xuxueli 2018-09-16 03:48:34
+ */
+@JobHandler(value="commandJobHandler")
+@Component
+public class CommandJobHandler extends IJobHandler {
+
+    @Override
+    public ReturnT<String> execute(String param) throws Exception {
+        String command = param;
+        int exitValue = -1;
+
+        BufferedReader bufferedReader = null;
+        try {
+            // command process
+            Process process = Runtime.getRuntime().exec(command);
+            BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream());
+            bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream));
+
+            // command log
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                XxlJobLogger.log(line);
+            }
+
+            // command exit
+            process.waitFor();
+            exitValue = process.exitValue();
+        } catch (Exception e) {
+            XxlJobLogger.log(e);
+        } finally {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+        }
+
+        if (exitValue == 0) {
+            return IJobHandler.SUCCESS;
+        } else {
+            return new ReturnT<String>(IJobHandler.FAIL.getCode(), "command exit value("+exitValue+") is failed");
+        }
+    }
+
+}