xxl-job入门

参考:
https://www.xuxueli.com/xxl-job

1. 总体架构

在这里插入图片描述

调度模块(调度中心):
负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块;
支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除,GLUE开发和任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover。

执行模块(执行器):
负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效;
接收“调度中心”的执行请求、终止请求和日志请求等。

源码仓库地址

源码仓库地址Release Download
https://github.com/xuxueli/xxl-jobDownload
https://gitee.com/xuxueli0323/xxl-jobDownload

中央仓库地址

<!-- http://repo1.maven.org/maven2/com/xuxueli/xxl-job-core/ -->
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>${最新稳定版本}</version>
</dependency>

源码目录

- /doc :文档资料
- /db :“调度数据库”建表脚本
- /xxl-job-admin :调度中心,项目源码
- /xxl-job-core :公共Jar依赖
- /xxl-job-executor-samples :执行器,Sample示例项目(大家可以在该项目上进行开发,也可以将现有项目改造生成执行器项目)

调度中心数据库

- xxl_job_lock:任务调度锁表;
- xxl_job_group:执行器信息表,维护任务执行器信息;
- xxl_job_info:调度扩展信息表: 用于保存XXL-JOB调度任务的扩展信息,如任务分组、任务名、机器地址、执行器、执行入参和报警邮件等等;
- xxl_job_log:调度日志表: 用于保存XXL-JOB任务调度的历史信息,如调度结果、执行结果、调度入参、调度机器和执行器等等;
- xxl_job_log_report:调度日志报表:用户存储XXL-JOB任务调度日志的报表,调度中心报表功能页面会用到;
- xxl_job_logglue:任务GLUE日志:用于保存GLUE更新历史,用于支持GLUE的版本回溯功能;
- xxl_job_registry:执行器注册表,维护在线的执行器和调度中心机器地址信息;
- xxl_job_user:系统用户表;

2. 启动调度中心

(1)初始调度数据库
db脚本位置:

xxl-job/doc/db/tables_xxl_job.sql

在这里插入图片描述
在这里插入图片描述

(2)修改调度中心配置
配置文件位置:

xxl-job/xxl-job-admin/src/main/resources/application.properties

在这里插入图片描述
修改db连接为第(1)步中导入的数据库,
修改报警邮箱设置,TODO
在这里插入图片描述
(3)启动调度中心
编译通过后可直接运行项目

xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/XxlJobAdminApplication.java

调度中心访问地址:

http://localhost:8080/xxl-job-admin
(该地址执行器将会使用到,作为回调地址)

默认登录账号:

admin / 123456

登录后运行界面如下图所示
在这里插入图片描述

3. 客户端集成执行器

以上示例均基于SpringBoot环境,

maven依赖
<!-- xxl-job-core -->
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.3.0</version>
</dependency>
集成Xxl-job配置

执行器端配置文件说明

### 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### 执行器通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=
### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
xxl.job.executor.appname=xxl-job-executor-sample
### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
xxl.job.executor.address=
### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
xxl.job.executor.ip=
### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
xxl.job.executor.port=9999
### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
xxl.job.executor.logretentiondays=30

注:
xxl.job.admin.addresses即对应调度中心地址,
xxl.job.executor.appname即对应执行器名称
一个调度中心可对应多个执行器名称
同一执行器名称可对应多个执行器运行实例
同一执行器运行实例可对应多个任务
调度中心根据执行器名称动态发现不同执行器集群的在线执行器运行实例列表,
进而在同一执行器名称下的不同运行实例间进行任务路由

执行器-1
执行器-2
运行实例1-1
运行实例1-2
运行实例1-3
任务1-1-1
任务1-1-2
任务1-1-3
运行实例2-1
运行实例2-2
运行实例2-3
任务2-1-1
任务2-1-2
调度中心
配置执行器组件
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
    logger.info(">>>>>>>>>>> xxl-job config init.");
    XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
    xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
    xxlJobSpringExecutor.setAppname(appname);
    xxlJobSpringExecutor.setIp(ip);
    xxlJobSpringExecutor.setPort(port);
    xxlJobSpringExecutor.setAccessToken(accessToken);
    xxlJobSpringExecutor.setLogPath(logPath);
    xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
    return xxlJobSpringExecutor;
}

3.1 BEAN模式

任务以JobHandler方式维护在执行器端,即

  1. 需要新建执行器代码工程
  2. 通过程序代码编写任务类形式IJobHandler、方法形式@XxlJob
  3. 并且需要在启动执行器工程后,再在调度中心控制台界面新建对应的执行器(执行器名称同xxl.job.executor.appname配置)
  4. 调度中心控制台界面新建对应的任务(通过执行器、JobHandler进行关联)
BEAN模式(类形式)- 实现IJobHandler
//BEAN模式(类形式) - 实现IJobHandler
class MyJobHandler implements IJobHandler {
	/**
	 * execute handler, invoked when executor receives a scheduling request
	 *
	 * @throws Exception
	 */
	public void execute() throws Exception;

	/**
	 * init handler, invoked when JobThread init
	 */
	public void init() throws Exception {
		// do something
	}


	/**
	 * destroy handler, invoked when JobThread destroy
	 */
	public void destroy() throws Exception {
		// do something
	}
}
[推荐]BEAN模式(方法形式)- 为Job方法添加注解@XxlJob
//BEAN模式(方法形式) - 为Job方法添加注解
@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")

@XxlJob("demoJobHandler")
public void demoJobHandler() throws Exception {
    XxlJobHelper.log("XXL-JOB, Hello World.");
}


//打印job日志,可通过调度中心控制台查看日志
XxlJobHelper.log("hello {}", "world");

//获取在调度中心控制台上设置的任务参数,
//字符串形式,由执行器端自己处理格式(如Json反序列化)
String jobParam = XxlJobHelper.getJobParam();
//借助任务参数,可实现诸如
//1. 通用HTTP任务Handler,参考SampleXxlJob.httpJobHandler
//2. 通用命令行Handler,参考SampleXxlJob.commandJobHandler

//获取分片参数
//shardIndex:当前分片序号(从0开始),执行器集群列表中当前执行器的序号;
//shardTotal:总分片数,执行器集群的总机器数量;
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();

//自主设置任务结果(默认不设置则表示成功)
XxlJobHelper.handleFail();
XxlJobHelper.handleFail(handleMsg);
XxlJobHelper.handleSuccess();
XxlJobHelper.handleSuccess(handleMsg);
新建BEAN模式任务

在这里插入图片描述
在这里插入图片描述

其中需要注意:
运行模式选择BEAN
JobHandler即对应@XxlJob(value="jobhandler名称")注解中的value值,
新建任务的配置属性详细说明如下:

`基础配置`"执行器":任务的绑定的执行器,任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另一方面也可以方便的进行任务分组。每个任务必须绑定一个执行器, 可在 : 执行器管理:  进行设置;
    "任务描述":任务的描述信息,便于任务管理;
    "负责人":任务的负责人;
    "报警邮件":任务调度失败时邮件通知的邮箱地址,支持配置多邮箱地址,配置多个邮箱地址时用逗号分隔;
    
`触发配置`"调度类型":
        无:该类型不会主动触发调度;
        CRON:该类型将会通过CRON,触发任务调度;
        固定速度:该类型将会以固定速度,触发任务调度;按照固定的间隔时间,周期性触发;
        固定延迟:该类型将会以固定延迟,触发任务调度;按照固定的延迟时间,从上次调度结束后开始计算延迟时间,到达延迟时间后触发下次调度;
    "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值;
    "执行参数":任务执行所需的参数;     
    
`高级配置`"路由策略":当执行器集群部署时,提供丰富的路由策略,包括;
        FIRST(第一个):固定选择第一个机器;
        LAST(最后一个):固定选择最后一个机器;
        ROUND(轮询):;
        RANDOM(随机):随机选择在线的机器;
        CONSISTENT_HASH(一致性HASH):每个任务按照Hash算法固定选择某一台机器,且所有任务均匀散列在不同机器上。
        LEAST_FREQUENTLY_USED(最不经常使用):使用频率最低的机器优先被选举;
        LEAST_RECENTLY_USED(最近最久未使用):最久未使用的机器优先被选举;
        FAILOVER(故障转移):按照顺序依次进行心跳检测,第一个心跳检测成功的机器选定为目标执行器并发起调度;
        BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;
        SHARDING_BROADCAST(分片广播):广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务;
    "子任务":每个任务都拥有一个唯一的任务ID(任务ID可以从任务列表获取),当本任务执行结束并且执行成功时,将会触发子任务ID所对应的任务的一次主动调度。
    "调度过期策":
        忽略:调度过期后,忽略过期的任务,从当前时间开始重新计算下次触发时间;
        立即执行一次:调度过期后,立即执行一次,并从当前时间开始重新计算下次触发时间;
    "阻塞处理策略":调度过于密集执行器来不及处理时的处理策略;
        单机串行(默认):调度请求进入单机执行器后,调度请求进入FIFO队列并以串行方式运行;
        丢弃后续调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,本次请求将会被丢弃并标记为失败;
        覆盖之前调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,将会终止运行中的调度任务并清空队列,然后运行本地调度任务;
    "任务超时时间":支持自定义任务超时时间,任务运行超时将会主动中断任务;
    "失败重试次数":支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;

3.2 GLUE模式(Java | Shell | Python | NodeJS | PHP | PowerShell)

任务以源码方式维护在调度中心,支持通过Web IDE在线更新,实时编译和生效,因此不需要指定JobHandler,
支持Java(extends IJobHandler)、Shell脚本(#!/bin/bash)、Python脚本(#!/usr/bin/python)、NodeJS、PHP、PowerShell。
以GLUE模式(Java)为例进行说明。

新建GLUE模式(Java)任务

在这里插入图片描述

在线开发任务代码

选中新创建的GLUE(Java)任务的操作->CLUE IDE,如下图
在这里插入图片描述

点击GLUE IDE按钮后即弹出如下在线编辑界面,可直接在这编辑代码(也可以在IDE中开发完成后,复制粘贴到这里)。
在这里插入图片描述

编辑完成后点击右上角保持,会提示输入源码备注,该备注可用于标识不同版本,方便后续版本回溯。
在这里插入图片描述
在这里插入图片描述

需要注意的时,GLUE(Java)模式需要注意如下几点:

  1. 新建任务时不需指定jobHandler
  2. 在线编辑的任务代码需要extends IJobHandler并实现逻辑;
  3. 在线编辑的任务代码支持@Autowired/@Resource注入执行器里中的其他服务(SpringBoot环境);

4. 其他操作

关于调度中心的更多操作,
如任务管理(启停、执行一次…)、
调度日志(备注、清理、执行日志、终止任务)、
执行器管理(手动|自动)…),
可参见官方文档: https://www.xuxueli.com/xxl-job/

5. 相关特性

5.1 调度中心HA(集群)

基于数据库的集群方案,数据库选用Mysql;
“调度中心”通过DB锁(select * from xxl_job_lock where lock_name = 'schedule_lock' for update)保证集群分布式调度的一致性,
假设同时存在调度中心A, B, C,
不同的调度中心在同一时刻仅有唯一的调度中心会获取到DB锁,
假如A获取锁成功,且A仅查询获取锁之后5秒内待触发的任务,
而其他调度中心B, C在获取锁的过程中会被阻塞,直到之前获取锁的调度中心A释放锁,
在A执行完调度释放锁后,其他的调度中心才可获取锁成功,
假如B成功获取锁(同样阻塞A, C),且B仅查询获取锁之后5秒内待触发的任务,
即通过DB锁来保证同一时刻仅有一个调度中心执行触发,且每次获取锁的调度中心会去触发不同时间段(拥有锁之后的5秒内)的任务。
具体细节可参见源码:com/xxl/job/admin/core/thread/JobScheduleHelper.start()

初始任务调度
启动触发线程池
启动调度
启动执行器注册监听器
启动任务失败监听器
启动任务完成监听器
启动日志上报
XxlJogAdminConfig.afterPropertiesSet
XxlJogScheduler.init
JobTriggerPoolHelper.toStart
JobSchedulerHelper.start
JobRegistryHelper.start
JobFailMonitorHelper.start
JobCompleteHelper.start
JobReportrHelper.start
创建快速触发器线程池
创建慢速触发器线程池
同一任务一分钟内超过10次调度开销在500ms以上,则使用slow线程池调度
新建schedulerThread
新建ringThread
JobTriggerPoolHelper.toStart
fastTriggerPool
slowTriggerPool
JobSchedulerHelper.start
scheduleThread
1.间隔1秒查询DB中5秒内待触发任务列表
2.补充触发misfire已过期5秒的任务
3.触发过期5秒内任务
4.未超时任务(包括第3步中的下一轮时间)添加到time ring队列
5.refreshNextValidTime并更新DB
ringThread
1.间隔1秒遍历时间环(1分钟范围)
2.取出时间环Map<second, jobIdList> ringData中当前秒数待触发的job列表
3.依次触发当前秒数对应的任务
4.清除时间环中当前秒数对应的任务列表
通过JobTriggerPoolHelper.trigger
添加触发任务到线程池
通过fast|slowTriggerPool
线程池调度
schedulerThread
ringThread
JobTriggerPoolHelper.addTrigger
XxlJobTrigger.trigger->processTrigger-> runExecutor
发起对执行器的http调用
XxlJobTrigger.trigger->processTrigger-> runExecutor
ExecutorBizClient.run
XxlJOgRemotingUtil.postBody(addressUrl/run, accessToken, triggerParam)
5.2 调度线程池

调度采用线程池方式实现,避免单线程因阻塞而引起任务调度延迟。
异步调度:调度中心每次任务触发时仅发送一次调度请求,该调度请求首先推送异步调度队列,然后异步推送给远程执行器
异步执行:执行器会将请求存入异步执行队列并且立即响应调度中心,异步运行。

在全异步化的基础上,调度中心中单个JOB一次调度平均耗时基本在 10ms 之内(基本为一次请求的网络开销);
因此,可以保证使用有限的线程支撑大量的JOB并发运行,
理论上默认配置下的调度中心,单机能够支撑 5000 任务并发运行稳定运行;

## 调度线程池最大线程配置【必填】
xxl.job.triggerpool.fast.max=200
# 同一任务一分钟内超过10次调度开销在500ms以上,则使用slow线程池调度
xxl.job.triggerpool.slow.max=100

实际场景中,由于调度中心与执行器网络ping延迟不同、DB读写耗时不同、任务调度密集程度不同,会导致任务量上限会上下波动。
如若需要支撑更多的任务量,可以通过 “调大调度线程数” 、”降低调度中心与执行器ping延迟” 和 “提升机器配置” 几种方式优化。

5.3 并行调度

XXL-JOB调度模块默认采用并行机制,在多线程调度的情况下,调度模块被阻塞的几率很低,大大提高了调度系统的承载量。

XXL-JOB的不同任务(即不同jobHandler)之间并行调度、并行执行
XXL-JOB的单个任务(相同jobHandler)
针对多个执行器并行运行的,
针对单个执行器串行执行的。
同时支持任务终止

关于任务终止详细参见:https://www.xuxueli.com/xxl-job#4.9 终止运行中的任务

参考:
进击的微服务实战派—上海站 > 分布式任务调度平台 XXL-JOB

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗小爬EX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值