xxl-job入门
引入
在平时的业务场景中,经常有一些场景需要使用定时任务,比如:
- 时间驱动的场景:系统需要定时每天0点进行数据备份,系统在某个时间点发送优惠券,发送短信等等;
- 批量处理数据:批量统计上个月的账单,统计上个月销售数据等等;
- 固定频率的场景:每隔5分钟需要执行一次。
这些场景问题都可以通过任务调度来解决,任务调度指的是系统在约定的指定时间自动执行指定任务的过程,简单来说,可以理解为规定在何时以何种方式自动去执行任务
在单体系统实现任务调度的方式:
- 多线程
- Timer
- Spring Tasks:@EnableScheduling + @Scheduled
有了上述几种实现任务调度的方式,为什么还需要分布式实现任务调度方式呢?
- 高可用:单机的定时任务只能在一台机器上运行,如果程序或者系统出现异常就会导致功能不可用;
- 防止重复执行:分布式部署多台服务,每台服务有定时任务,如果不进行合理的控制,在同一时间,只有一个定时任务启动执行,这时,定时执行的结果就可能存在错误和混乱;
- 单机处理极限:单机处理能力有限
分布式实现任务调度的方式:
xxl-job- Quartz
- elastic-job
xxl-job
xxl-job实现定时任务可以理解为是通过任务调度平台和执行器相互通信,从而达到实现定时任务的目的。
xxl-job中的两个核心概念:
- 调度平台:负责管理调度信息,按照调度的配置发出调度请求(xxl-job提供可视化界面,程序员直接进入调度平台按照要求配置即可,无需编写代码)
- 执行器:负责接收调度请求,执行调度任务的业务逻辑(由程序员编写代码实现具体执行的逻辑)。执行器启动后要注册到调度中心,接收调度中心发出的请求
xxl-job原理图
xxl-job实战
下载
到官网下载zip
配置部署调度中心
- 解压下载好的文件,打开/doc/db/tables_xxl_job.sql
- 复制sql,到数据库中执行(以dbeaver为例)
- 将指定文件复制到sql编辑器中,依条执行,执行成功后,会生成一个xxl_job数据库
- 用idea打开下载好的项目xxl-job-master,修改配置文件数据库相关信息,按照自己数据库的地址,账号和密码配置,配置后启动
- 成功启动后,访问调度中心,访问地址为:http://localhost:8080/xxl-job-admin,默认登录账号 “admin/123456”
- 登录成功后,进入任务调度中心,主界面如图所示
配置部署执行器
- 创建Springboot项目xxljobDemo,pom文件中添加相关依赖
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
- 修改配置文件application.properties,保持与xxl-job-master中的配置一致,注意需要配置下服务器端口,避免冲突
server.port = 8088
### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### 执行器通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=default_token
### 执行器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配置类
@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;
}
}
编写任务
- 新建job包,包下定义SimpleJob类,类中定义具体任务
@Component
public class SimpleJob {
@XxlJob("demoJobHander")
public void demoJobHandler() throws Exception{
System.out.println("执行定时任务,执行时间:" + new Date());
}
}
- 启动项目xxljobDemo
- 启动成功后,进入任务调度中心设置执行器相关信息
- 配置完成后,启动任务,任务状态由stop-->running状态
通过控制台可以看到,我们规定的任务隔3s执行一次
- 任务停止后,状态由running-->stop
- 可以通过查看日志按钮查看调度日志
这样就实现了一个简单的定时任务!