xxl-job:一个分布式的定时器管理平台(这东西类似于zookeeper)
开源地址:https://github.com/xuxueli/xxl-job
我启动后,配置了一个项目,测试了以下几个内容
去开源地址上把xxl_job_admin下载下来,把数据库脚本导入到数据库,启动项目即可,它是个标准的springboot项目,注意访问的时候要带上path,因为作者在配置文件里配置了访问的path /xxl-job-admin
可以从开源地址中的 xxl-job-executor-samples
中找到对应项目架构的例子,下面是springboot项目的配置方法
首先引入依赖
<dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.1.2</version> </dependency>
加入配置类
package ai.puying.insuredata.config; import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * xxl-job config * 文链接原: [https://tomoya92.github.io/2020/04/08/xxl-job-feature-with-test/](https://tomoya92.github.io/2020/04/08/xxl-job-feature-with-test/) * @author xuxueli 2017-04-28 */ @Configuration public class XxlJobConfig { private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class); @Value("${xxl.job.admin.address}") 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); // 最新的快照版里有这个参数的设置,但mvn中心库中的版本里没有这个参数,这里注释掉 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(); */ }
文接链原: https://tomoya92.github.io/2020/04/08/xxl-job-feature-with-test/
然后在项目中的定时器任务的方法上加上注解 @XxlJob("testJob")
@Component public class SchedulingService { @XxlJob("testJob") public ReturnT<String> job1(String param) { // do stuff.. // return new ReturnT<>(ReturnT.FAIL.getCode(), "error message"); return ReturnT.SUCCESS; } }
注意,方法的参数必须要加上,不加启动会报错
剩下的就是在job_admin上配置任务了
昨天我才知道的,springboot项目自带的定时器他们是共用一个线程的,比如我在一个项目里写了2个定时器,第一个定时器执行一次要耗时10s,第二个要耗时20s,定时任务都是5s一次
假如在2020-04-08 15:51:00 定时器开始执行,如果先执行的是第一个定时器,那么在15:51:10的时候,会执行完,定时间隔是5s,也就是说在 15:51:10 的时候会继续执行第一个定时器,但springboot默认是只给一个线程的,它会等着第二个定时器执行完,也就是还要再等10s,到 15:51:20的时候才会继续下一轮的定时任务
如果要解决这问题,可以在方法中添加上单独的线程,也可以使用 @Async
注解,不过这两种方法都不是好的选择,很容易就把线程池给用爆了
这时候就体现出了xxl-job这种定时任务管理的好处了!
原文链接: