单机模式中的定时任务很简单,一般使用@EnableScheduling 就可以了,但是在集群中,这个简单的定时任务就不行了,会有问题;
例如我要在半夜12点执行一个任务,发送一条短信给一个用户,但是当为集群的时候,这种简单的任务,在多个节点上,都会执行,那么就会造成任务的重复执行,每个用户都接受到了多条相同的短信,这种错误还好,但是当涉及到计算等问题的时候,这种错误就是致命的,而且当没有集群经验的时候,这种问题在单机情况下还是正常,集群就会出现大问题!!!
大神徐雪里开源的定时任务框架;
官方文档: 文档
源码地址: 服务端源码,客户端示例
大体使用步骤: 引用我的上一篇文章 传送门
上一篇文章主要是讲了如何测试xxl-job,那么实际项目中,如何使用呢?
就是这个地址: 服务端源码,客户端示例
由于xxl-job的思想是 调度中心负责调度任务,然后有执行器负责接受调度的信息,然后根据调度,执行任务中的具体逻辑
**第一步: **
将 xl-job-admin 启动起来,操作xl-job-admin这个文件夹下的配置文件即可
我们想要自己搞一个任务执行器,也就是要弄一个这样的服务
com.xuxueli
xxl-job-core
2.3.1
xxl:
job:
accessToken: default_token
admin:
# 调度中心服务地址
addresses: http://127.0.0.1:8080/xxl-job-admin
executor:
address: ''
# 必须唯一 执行器名称
appname: jobhandel
ip: ''
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: 30
# 执行器回调端口,用于接受调度消息
port: 9998
直接粘贴示例源码
/**
* xxl-job config
*
* @author xuxueli 2017-04-28
*/
@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(IpUtil.getIp());
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
/**
* 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;
*
* 1、引入依赖:
*
* org.springframework.cloud
* spring-cloud-commons
* ${version}
*
*
* 2、配置文件,或者容器启动变量
* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
*
* 3、获取IP
* String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
*/
}
其实完全仿照的就是 com.xxl.job.executor.service.jobhandler.SampleXxlJob类
@Component
public class AssetsTask {
/**
* XxlJob开发示例(Bean模式)
*
* 开发步骤:
* 1、任务开发:在Spring Bean实例中,开发Job方法;
* 2、注解配置:为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。
* 3、执行日志:需要通过 "XxlJobHelper.log" 打印执行日志;
* 4、任务结果:默认任务结果为 "成功" 状态,不需要主动设置;如有诉求,比如设置任务结果为失败,可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果;
*
* @author xuxueli 2019-12-11 21:52:51
*/
private static Logger logger = LoggerFactory.getLogger(AssetsTask.class);
/**
* 1、简单任务示例(Bean模式)
*/
@XxlJob("testJobHandler")
public void demoJobHandler() throws Exception {
XxlJobHelper.log("XXL-JOB, Hello World.");
System.out.println("XXL-JOB, Hello World." + DateUtil.now());
}
}
出现此日志,说明服务启动成功,且与xxl-job调度中心通信成功
至此,我们完成了xxl-job服务端的配置启动,xxl-job客户端的配置,以及执行器/任务的添加,然后就完成了定时任务的灵活调度,随时启停,更改定时任务调度,以及解决多实例中任务重复执行的问题;
实际项目中:
当然xxl-job还有一个GLUE(Java)模式,我感觉在实际项目中,应用场景应该不多,相当于脱离了数据库的执行,感觉用不上,这里不做赘述了;