XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。它的有两个核心模块,一个模块叫作调度中心,另一个模块叫作执行器,它把任务调度和任务执行分红两个部分。这样调度模块只须要负责任务的调度属性,触发调度信号。执行模块只须要接收调度信号,去执行具体的业务逻辑,二者能够各自的进行扩容和缩容。图1是一张来自官方的架构图。php
既然是一个分布式调度平台,确定会有一个调度中心,固然执行器(被调度者)也是必不可少的,能够参考架构图。因此,使用xxl-job搭建一个demo,也必须有两个端,下面本文分别从准备工做、搭建“调度中心”、搭建“执行器”三个部分进行说明。java
源码地址:https://github.com/xuxueli/xxl-jobnode
我使用的源码是2.2.0版本,这是目前最新的release版本。python
源码包含了文档(数据库初始化脚本、官方文档、架构图等)、调度中心源码、核心core、各个版本的执行器源码。如图2所示:mysql
2.1.2 数据库准备
数据库脚本在doc路径下,将其执行以后能够建立一个数据库,如图3所示:git
将数据库链接信息和报警信息配置成本身的,配置文件以下:github
### web server.port=8080 server.servlet.context-path=/xxl-job-admin ### actuator management.server.servlet.context-path=/actuator management.health.mail.enabled=false ### resources spring.mvc.servlet.load-on-startup=0 spring.mvc.static-path-pattern=/static/** spring.resources.static-locations=classpath:/static/ ### freemarker spring.freemarker.templateLoaderPath=classpath:/templates/ spring.freemarker.suffix=.ftl spring.freemarker.charset=UTF-8 spring.freemarker.request-context-attribute=request spring.freemarker.settings.number_format=0.########## ### mybatis mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml #mybatis.type-aliases-package=com.xxl.job.admin.core.model ### xxl-job, datasource spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ### datasource-pool spring.datasource.type=com.zaxxer.hikari.HikariDataSource spring.datasource.hikari.minimum-idle=10 spring.datasource.hikari.maximum-pool-size=30 spring.datasource.hikari.auto-commit=true spring.datasource.hikari.idle-timeout=30000 spring.datasource.hikari.pool-name=HikariCP spring.datasource.hikari.max-lifetime=900000 spring.datasource.hikari.connection-timeout=10000 spring.datasource.hikari.connection-test-query=SELECT 1 ### xxl-job, email spring.mail.host=smtp.qq.com spring.mail.port=25 spring.mail.username=xxx@qq.com spring.mail.password=xxx spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.required=true spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory ### xxl-job, access token xxl.job.accessToken= ### xxl-job, i18n (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en") xxl.job.i18n=zh_CN ## xxl-job, triggerpool max size xxl.job.triggerpool.fast.max=200 xxl.job.triggerpool.slow.max=100 ### xxl-job, log retention days xxl.job.logretentiondays=30
在IDEA里面直接运行,若是使用的是macOS系统的话,可能会出现错误:Failed to create parent directories for [/data/applogs/xxl-job/xxl-job-admin.log],如图4所示:web
解决办法是:将logback.xml中的“/data/applogs/xxl-job/xxl-job-admin.log”改成“./data/applogs/xxl-job/xxl-job-admin.log”,如图5所示。后续在测试运行的时候,执行器端会抛出相似异常,用一样的方式能够解决。算法
启动以后浏览器访问http://localhost:8080/xxl-job-admin,使用默认的用户名(admin)和密码(123456)登录以后,能够看到如图6所示页面:spring
使用IDEA新建一个Spring Boot项目:xxl-job-executor
Maven依赖:
<dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.2.0</version> </dependency>
主要须要配置xxl-job的调度中心地址信息、xxl-job执行器相关信息。配置文件以下:
# web port server.port=8081 # no web #spring.main.web-environment=false # log config logging.config=classpath:logback.xml ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin ### xxl-job, access token xxl.job.accessToken= ### xxl-job executor appname xxl.job.executor.appname=xxl-job-executor-test ### 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
还要建立一个XxlJobConfig.java配置执行器。代码以下:
@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; } }
固然还要添加logback.xml文件。
代码以下:
@Component public class TestXxlJobHandler { private static Logger logger = LoggerFactory.getLogger(TestXxlJobHandler.class); /** * 一、简单任务示例(Bean模式) */ @XxlJob("testJobHandler") public ReturnT<String> demoJobHandler(String param) throws Exception { System.out.println(new Date() + "Test Xxl-Job~"); return ReturnT.SUCCESS; } }
完成以后的整个代码结构如图8所示:
在本机运行调度中心和执行器。
在调度中心新增一个测试执行器,AppName为xxl-job-executor-test,名称为测试执行器,注册方式选择自行注册便可,如图9所示:
新增一个任务,名称与代码中名称一致,配置为每2分钟执行一次,路由策略为一致性HASH,运行模式为BEAN,阻塞处理策略为单机串行,配置如图10所示:
详细配置属性能够参考:
● 执行器:任务的绑定的执行器,任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另外一方面也能够方便的进行任务分组。每一个任务必须绑定一个执行器, 可在 "执行器管理" 进行设置;
● 任务描述:任务的描述信息,便于任务管理;
● 路由策略:当执行器集群部署时,提供丰富的路由策略,包括;
FIRST(第一个):固定选择第一个机器;
LAST(最后一个):固定选择最后一个机器;
ROUND(轮询):;
RANDOM(随机):随机选择在线的机器;
CONSISTENT_HASH(一致性HASH):每一个任务按照Hash算法固定选择某一台机器,且全部任务均匀散列在不一样机器上。
LEAST_FREQUENTLY_USED(最不常用):使用频率最低的机器优先被选举;
LEAST_RECENTLY_USED(最近最久未使用):最久未使用的机器优先被选举;
FAILOVER(故障转移):按照顺序依次进行心跳检测,第一个心跳检测成功的机器选定为目标执行器并发起调度;
BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;
SHARDING_BROADCAST(分片广播):广播触发对应集群中全部机器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务;
● Cron:触发任务执行的Cron表达式;
● 运行模式:
BEAN模式:任务以JobHandler方式维护在执行器端;须要结合 "JobHandler" 属性匹配执行器中任务;
GLUE模式(Java):任务以源码方式维护在调度中心;该模式的任务其实是一段继承自IJobHandler的Java类代码并 "groovy" 源码方式维护,它在执行器项目中运行,可以使用@Resource/@Autowire注入执行器里中的其余服务;
GLUE模式(Shell):任务以源码方式维护在调度中心;该模式的任务其实是一段 "shell" 脚本;
GLUE模式(Python):任务以源码方式维护在调度中心;该模式的任务其实是一段 "python" 脚本;
GLUE模式(PHP):任务以源码方式维护在调度中心;该模式的任务其实是一段 "php" 脚本;
GLUE模式(NodeJS):任务以源码方式维护在调度中心;该模式的任务其实是一段 "nodejs" 脚本;
GLUE模式(PowerShell):任务以源码方式维护在调度中心;该模式的任务其实是一段 "PowerShell" 脚本;
● JobHandler:运行模式为 "BEAN模式" 时生效,对应执行器中新开发的JobHandler类“@JobHandler”注解自定义的value值;
● 阻塞处理策略:调度过于密集执行器来不及处理时的处理策略;
单机串行(默认):调度请求进入单机执行器后,调度请求进入FIFO队列并以串行方式运行;
丢弃后续调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,本次请求将会被丢弃并标记为失败;
覆盖以前调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,将会终止运行中的调度任务并清空队列,而后运行本地调度任务;
● 子任务:每一个任务都拥有一个惟一的任务ID(任务ID能够从任务列表获取),当本任务执行结束而且执行成功时,将会触发子任务ID所对应的任务的一次主动调度。
● 任务超时时间:支持自定义任务超时时间,任务运行超时将会主动中断任务;
● 失败重试次数;支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;
● 报警邮件:任务调度失败时邮件通知的邮箱地址,支持配置多邮箱地址,配置多个邮箱地址时用逗号分隔;
● 负责人:任务的负责人;
● 执行参数:任务执行所需的参数;
启动调度任务,如图11所示:
能够查看日志或者控制台信息,运行结果满意,如图12所示:
在控制台运行报表界面也能够看到调度和执行状况,如图13所示。图中那一次调度失败是因为执行器重启,形成了调度中心调度任务的时候发现调度地址为空,因此执行失败。
参考文档:官方中文文档