XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
admin下载及安装 下载 1 2 git clone https://gi thub.com/xuxueli/ xxl-job.git cd xxl-job
切换分支 切换到最新分支,当前最新2.2.0
修改文件
根据自身情况修改文件xxl-job-admin/src/main/resources/application.properties
,主要修改数据库及email相关配置
修改文件xxl-job-admin/src/main/resources/logback.xml
中的log.path
打包 1 mvn clean install package
数据库 将文件doc/db/tables_xxl_job.sql
导入数据库
1 mysql -uroot -p < doc/db/ tables_xxl_job.sql
运行 1 java -jar xxl-job-admin/target/xxl-job-admin-2 .2 .0 .jar
查看 访问http://localhost:8080/xxl-job-admin
初始账号及密码admin
,123456
与spring boot集成 添加依赖 gradle
1 implementation 'com.xuxueli:xxl-job-core:2 .2 .0 '
maven
1 2 3 4 5 <dependency > <groupId > com.xuxueli</groupId > <artifactId > xxl-job-core</artifactId > <version > 2.2.0</version > </dependency >
添加配置 在application.properties
中添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" xxl.job.admin.addresses=http: ### xxl-job, access token xxl.job.accessToken= ### xxl-job executor appname xxl.job.executor.appname=xxl-job-executor-sample ### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null xxl.job.executor.address= ### xxl-job executor server-info xxl.job.executor.ip= xxl.job.executor.port=9999 ### xxl-job executor log-path xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler ### xxl-job executor log-retention-days xxl.job.executor.logretentiondays=30
添加bean 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 package com.xxl.job.executor.core.config;import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation .Value;import org.springframework.context.annotation .Bean;import org.springframework.context.annotation .Configuration;@Configuration public class XxlJobConfig { private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class ); @Value("${xxl.job.admin.addresses} " ) private String adminAddresses; @Value("${xxl.job.accessToken} " ) private String accessToken; @Value("${xxl.job.executor.appname} " ) private String appname; @Value("${xxl.job.executor.address} " ) private String address; @Value("${xxl.job.executor.ip} " ) private String ip; @Value("${xxl.job.executor.port} " ) private int port; @Value("${xxl.job.executor.logpath} " ) private String logPath; @Value("${xxl.job.executor.logretentiondays} " ) private int logRetentionDays; @Bean public XxlJobSpringExecutor xxlJobExecutor() { logger.info(">>>>>>>>>>> xxl-job config init." ); XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); xxlJobSpringExecutor.setAdminAddresses(adminAddresses); xxlJobSpringExecutor.setAppname(appname); xxlJobSpringExecutor.setAddress(address); xxlJobSpringExecutor.setIp(ip); xxlJobSpringExecutor.setPort(port); xxlJobSpringExecutor.setAccessToken(accessToken); xxlJobSpringExecutor.setLogPath(logPath); xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); return xxlJobSpringExecutor; } }
使用案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 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.XxlJob;import com.xxl.job.core.log.XxlJobLogger;import com.xxl.job.core.util.ShardingUtil;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;import java.util.Arrays;import java.util.concurrent.TimeUnit;@Component public class SampleXxlJob { private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class); @XxlJob("demoJobHandler") public ReturnT<String> demoJobHandler (String param) throws Exception { XxlJobLogger.log("XXL-JOB, Hello World." ); for (int i = 0 ; i < 5 ; i++) { XxlJobLogger.log("beat at:" + i); TimeUnit.SECONDS.sleep(2 ); } return ReturnT.SUCCESS; } @XxlJob("shardingJobHandler") public ReturnT<String> shardingJobHandler (String param) throws Exception { ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); XxlJobLogger.log("分片参数:当前分片序号 = {}, 总分片数 = {}" , shardingVO.getIndex(), shardingVO.getTotal()); for (int i = 0 ; i < shardingVO.getTotal(); i++) { if (i == shardingVO.getIndex()) { XxlJobLogger.log("第 {} 片, 命中分片开始处理" , i); } else { XxlJobLogger.log("第 {} 片, 忽略" , i); } } return ReturnT.SUCCESS; } @XxlJob("commandJobHandler") public ReturnT<String> commandJobHandler (String param) throws Exception { String command = param; int exitValue = -1 ; BufferedReader bufferedReader = null ; try { Process process = Runtime.getRuntime().exec(command); BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream()); bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream)); String line; while ((line = bufferedReader.readLine()) != null ) { XxlJobLogger.log(line); } 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" ); } } @XxlJob("httpJobHandler") public ReturnT<String> httpJobHandler (String param) throws Exception { if (param==null || param.trim().length()==0 ) { XxlJobLogger.log("param[" + param +"] invalid." ); return ReturnT.FAIL; } String[] httpParams = param.split("\n" ); String url = null ; String method = null ; String data = null ; for (String httpParam: httpParams) { if (httpParam.startsWith("url:" )) { url = httpParam.substring(httpParam.indexOf("url:" ) + 4 ).trim(); } if (httpParam.startsWith("method:" )) { method = httpParam.substring(httpParam.indexOf("method:" ) + 7 ).trim().toUpperCase(); } if (httpParam.startsWith("data:" )) { data = httpParam.substring(httpParam.indexOf("data:" ) + 5 ).trim(); } } if (url==null || url.trim().length()==0 ) { XxlJobLogger.log("url[" + url +"] invalid." ); return ReturnT.FAIL; } if (method==null || !Arrays.asList("GET" , "POST" ).contains(method)) { XxlJobLogger.log("method[" + method +"] invalid." ); return ReturnT.FAIL; } HttpURLConnection connection = null ; BufferedReader bufferedReader = null ; try { URL realUrl = new URL(url); connection = (HttpURLConnection) realUrl.openConnection(); connection.setRequestMethod(method); connection.setDoOutput(true ); connection.setDoInput(true ); connection.setUseCaches(false ); connection.setReadTimeout(5 * 1000 ); connection.setConnectTimeout(3 * 1000 ); connection.setRequestProperty("connection" , "Keep-Alive" ); connection.setRequestProperty("Content-Type" , "application/json;charset=UTF-8" ); connection.setRequestProperty("Accept-Charset" , "application/json;charset=UTF-8" ); connection.connect(); if (data!=null && data.trim().length()>0 ) { DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream()); dataOutputStream.write(data.getBytes("UTF-8" )); dataOutputStream.flush(); dataOutputStream.close(); } int statusCode = connection.getResponseCode(); if (statusCode != 200 ) { throw new RuntimeException("Http Request StatusCode(" + statusCode + ") Invalid." ); } bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8" )); StringBuilder result = new StringBuilder(); String line; while ((line = bufferedReader.readLine()) != null ) { result.append(line); } String responseMsg = result.toString(); XxlJobLogger.log(responseMsg); return ReturnT.SUCCESS; } catch (Exception e) { XxlJobLogger.log(e); return ReturnT.FAIL; } finally { try { if (bufferedReader != null ) { bufferedReader.close(); } if (connection != null ) { connection.disconnect(); } } catch (Exception e2) { XxlJobLogger.log(e2); } } } @XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy") public ReturnT<String> demoJobHandler2 (String param) throws Exception { XxlJobLogger.log("XXL-JOB, Hello World." ); return ReturnT.SUCCESS; } public void init () { logger.info("init" ); } public void destroy () { logger.info("destory" ); } }
添加执行器
登录admin
点击左侧执行器管理
–新增
AppName填写xxl-job-executor-sample
,名称根据实际情况输入,注册方式选择自动注册,保存.
刷新列表即可看到OnLine机器地址
添加任务
点击新增
按钮
执行器选中xxl-job-executor-sample
根据实际情况填写,其中JobHandler填写@XxlJob
的值,如案例中的demoJobHandler
保存