前言

XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
官方地址中文版:http://www.xuxueli.com/xxl-job

一、Quartz的对比

Quartz作为开源作业调度中的佼佼者,是作业调度的首选。集群环境中Quartz采用API的方式对任务进行管理,Quartz存在以下问题:

  • 调用API的的方式操作任务,不人性化
  • 需要持久化业务QuartzJobBean到底层数据表中,系统侵入性相当严重
  • 调度逻辑和QuartzJobBean耦合在同一个项目中,调度系统的性能将大大受限于业务
  • quartz底层以“抢占式”获取DB锁并由抢占成功节点负责运行任务,节点负载悬虚大,而XXL-JOB通过执行器实现“协同分配式”运行任务,负载各个节点

二、XXL-JOB特性

XXL-JOB特性太过于多,这里就挑几个有点比较大的来说说

  • 简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手
  • 调度中心HA(中心式):调度采用中心式设计,“调度中心”基于集群Quartz实现并支持集群部署,可保证调度中心HA
  • 执行器HA(分布式):任务分布式执行,任务"执行器"支持集群部署
  • 任务失败重试:支持自定义任务失败重试次数
  • 邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件
  • 自定义任务参数:支持在线配置调度任务入参,即时生效
  • 跨平台:原生提供通用HTTP任务Handler(Bean任务,"HttpJobHandler"),业务方只需要提供HTTP链接即可,不限制语言、平台
  • 全异步:任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰,理论上支持任意时长任务的运行
  • 容器化:提供官方docker镜像,并实时更新推送dockerhub,进一步实现产品开箱即用
  • 线程池隔离:调度线程池进行隔离拆分,避免耗尽调度线程,提高系统稳定性
  • 一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行

使用xxl-job需要两大步骤,分为客户端(源码下载启动后台),服务端

三、快速入门(客户端)

3.1、官网下载源码

image.png

  • xxl-job-admin:调度中心
  • xxl-job-core:公共依赖
  • xxl-job-executor-samples:执行器Sample示例

3.2、初始化"调度数据库"

SQL脚本位置:/xxl-job/doc/db/tables_xxl_job.sql

注意⚠️:调度中心支持集群部署,集群情况下各节点务必连接同一个mysql实例;
如果mysql做主从,调度中心集群节点务必强制走主库

3.3、修改xxl-job-admin配置

我这里就把需要改的几个地方列出来了

### 端口,随自己修改
server.port=8096
server.servlet.context-path=/xxl-job-admin
### 数据库
spring.datasource.url=jdbc:mysql://49.233.170.48:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=Qw941104/
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

### 邮箱(qq邮箱密码你要去查看授权码)
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=1050674486@qq.com
spring.mail.from=1050674486@qq.com
spring.mail.password=
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.login.username=admin
xxl.job.login.password=123456

3.4、启动部署

http://127.0.0.1:8096/xxl-job-admin
界面
image.png

至此“调度中心”项目已经部署成功。

四、springboot整合执行器项目

4.1、examples范例

你说下载的项目中这个就是范例,有不同版本,我下面自己搭建
image.png

4.2、依赖引入

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:$springbootWebVersion")
    compile("com.xuxueli:xxl-job-core:2.2.0")
}

4.2、配置

其中注意xxl.job.admin.addresses

# web port
server.port=8095
# 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:8096/xxl-job-admin
### 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

4.3、配置

@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;
    }

    /**
     * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;
     *
     *      1、引入依赖:
     *          <dependency>
     *             <groupId>org.springframework.cloud</groupId>
     *             <artifactId>spring-cloud-commons</artifactId>
     *             <version>${version}</version>
     *         </dependency>
     *
     *      2、配置文件,或者容器启动变量
     *          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
     *
     *      3、获取IP
     *          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
     */
}

到这里我们就搭建好了,接下来开发自己的任务

五、自定义任务

5.1、自定义任务

@Component
public class SampleXxlJob {

    @Autowired
    DemoJobService demoJobService;
    /**
     * 1、简单任务示例(Bean模式)
     */
    @XxlJob("demoJobHandler")
    public ReturnT<String> execute(String param) {
        XxlJobLogger.log("hello world.");
        demoJobService.demoTest(param);
        return ReturnT.SUCCESS;
    }

}

4.5、逻辑处理(不重要)

@Service
@Slf4j
public class DemoJobService {
    public void demoTest(String s1) {
        log.info("====逻辑处理中==========参数:{}", s1);
    }
}

5.2、客户端新建执行器

image.png

5.3、客户端新建任务

image.png

5.4、启动或者执行一次

image.png

5.5、控制台打印日志

image.png

六、配置属性详细说明:

  • 执行器:任务的绑定的执行器,任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另一方面也可以方便的进行任务分组。每个任务必须绑定一个执行器, 可在 "执行器管理" 进行设置;

  • 任务描述:任务的描述信息,便于任务管理;

  • 路由策略:当执行器集群部署时,提供丰富的路由策略,包括;
    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所对应的任务的一次主动调度。

  • 任务超时时间:支持自定义任务超时时间,任务运行超时将会主动中断任务;

  • 失败重试次数;支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;

  • 报警邮件:任务调度失败时邮件通知的邮箱地址,支持配置多邮箱地址,配置多个邮箱地址时用逗号分隔;

  • 负责人:任务的负责人;

  • 执行参数:任务执行所需的参数;

七、注意事项

7.1、报错:The correct method format like " public ReturnT execute(String param) "

你开发的自定义任务bean返回错误或者参数

7.2、报错500

请检查你的依赖是否冲突

上一篇 下一篇