实现elastic-job分布式调度框架的spring boot自动装载
背景
- 每个复杂的项目都存在大量重要的定时调度任务,引入一个好用的分布式调度任务框架是非常重要的。elastic job是当当网开源的基于quartz的分布式调度框架,通过zookeeper实现分布式协调,加上支持分片、日志追踪、任务管理UI、高可性被大家熟知。
- 目前新的项目基本都是spring boot,如何通过约束、配置方式快速构建elastic job是一个必要解决问题 ;所以博主自己开发了一个elastic job 的spring boot starter自动装载模块;目前该starter已经在公司多个项目生产环境运行。研发只需关注实现job和在application.yml增加相应配置即可。
运行环境
1.JDK1.8
2.MAVEN3.3+
3.Spring boot 2.1.17.RELEASE
4.Zookeeper 3.4.6
源代码下载
https://download.csdn.net/download/m0_38138879/19421275
第三方依赖关系
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>com.dangdang</groupId> <artifactId>elastic-job-lite-core</artifactId> <version>2.1.5</version> </dependency> <dependency> <groupId>com.dangdang</groupId> <artifactId>elastic-job-lite-spring</artifactId> <version>2.1.5</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-client</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.10.0</version> </dependency> </dependencies>
核心配置代码
1.绑定注册中心配置信息的POJO
package cn.hrs.tools.spring.elasticjob.properties;
import lombok.Data;
/**
* @author huangrusheng
* @version 1.0
* @date 2021/6/6 11:04
*/
@Data
public class ZookeeperRegistryCenterProperties {
/**
* 连接Zookeeper服务器的列表.
* 包括IP地址和端口号.
* 多个地址用逗号分隔.
* 如: host1:2181,host2:2181
*/
private String serverLists;
/**
* 命名空间.
*/
private String namespace;
/**
* 等待重试的间隔时间的初始值.
* 单位毫秒.
*/
private int baseSleepTimeMilliseconds = 1000;
/**
* 等待重试的间隔时间的最大值.
* 单位毫秒.
*/
private int maxSleepTimeMilliseconds = 3000;
/**
* 最大重试次数.
*/
private int maxRetries = 3;
/**
* 会话超时时间.
* 单位毫秒.
*/
private int sessionTimeoutMilliseconds;
/**
* 连接超时时间.
* 单位毫秒.
*/
private int connectionTimeoutMilliseconds;
/**
* 连接Zookeeper的权限令牌.
* 缺省为不需要权限验证.
*/
private String digest;
}
2.绑定调度任务配置的POJO
package cn.hrs.tools.spring.elasticjob.properties;
import lombok.Data;
/**
* @author huangrusheng
* @version 1.0
* @date 2021/6/6 11:04
*/
@Data
public class JobProperties {
/**
* 支持值 simpleJob、dataFlowJob,scriptJob ,默认为simpleJob
*/
private String jobType = "simpleJob";
/**
* 下参数二选一,要么填JOB的className或已经spring依赖管理的job bean name.
*/
private String className;
private String jobRef;
/**
* 注册中心的bean名称
*/
private String registryRef = "zookeeperRegistryCenter";
/**
* Job的名称
*/
private String jobName;
/**
* 调度cron表达式
*/
private String cron;
/**
* 总分片数
*/
private int shardingTotalCount;
/**
* 每个分片的参数,用逗号分隔
*/
private String shardingItemParameters = "";
/**
* job的参数
*/
private String jobParameter = "";
/**
* elastic job是通过数据库记录运行日志,设置DataSource的bean name,elastic job会自动创建表
*/
private String eventTraceRdbDataSourceRef;
/**
* 是否开启故障转移
*/
private boolean failover;
/**
* 是否开启错过重跑
*/
private boolean misfire = true;
private String description = "";
private String executorServiceHandler;
private String jobExceptionHandler;
private boolean monitorExecution = true;
private int maxTimeDiffSeconds = -1;
private int monitorPort = -1;
private String jobShardingStrategyClass = "";
private int reconcileIntervalMinutes = 10 ;
private boolean disabled;
private boolean overwrite;
private ListenerProperties listener;
private DistributedListenerProperties distributedListener;
/**
* dataFlowJob 才生效的字段
*/
private boolean streamingProcess;
/**
* scriptJob 才生效的字段
*/
private String scriptCommandLine;
}
3.Spring Boot starter的配置POJO
package cn.hrs.tools.spring.elasticjob.autoconfig;
import cn.hrs.tools.spring.elasticjob.properties.JobProperties;
import cn.hrs.tools.spring.elasticjob.properties.ZookeeperRegistryCenterProperties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author huangrusheng
* @version 1.0
* @date 2021/6/6 11:04
*/
@ConfigurationProperties(prefix = ElasticJobProperties.prefix )
@Data
public class ElasticJobProperties {
public static final String prefix= "elastic-job";
private ZookeeperRegistryCenterProperties registryCenter ;
private Map<String, JobProperties> jobs = new LinkedHashMap<>();
}
Demo使用案例
1.引入上述建立的spring boot starter依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>cn.hrs.tools.spring</groupId> <artifactId>elasticjob-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
2.定义JOB
package cn.hrs.tools.demo.elasticjob;
import cn.hutool.core.thread.ThreadUtil;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @author huangrusheng
* @version 1.0
* @date 2021/6/6 11:06
*/
@Slf4j
@Component("mySimpleJob")
public class MySimpleJob implements SimpleJob {
@Override
public void execute(ShardingContext shardingContext) {
log.info("启动测试分布式调度elastic job 任务..");
log.info("当前总分片数:{},当前分片的参数:{}",shardingContext.getShardingTotalCount(),shardingContext.getShardingParameter());
log.info("当前job名称:{},job设置的参数:{}",shardingContext.getJobName(),shardingContext.getJobParameter());
ThreadUtil.sleep(10, TimeUnit.SECONDS);
log.info("完成测试分布式调度elastic job 任务..");
}
}
3.application.yml配置调度任务
elastic-job:
registryCenter:
serverLists: 172.16.110.115:2181 #请改为自己的zookeeper地址.
namespace: elastic-job-demo
jobs:
mySimpleJob:
jobType: simpleJob
jobRef: mySimpleJob
jobName: "测试分布式调度任务"
jobParameter: "type=23"
cron: 0 0/2 * * * ? *
shardingTotalCount: 2
shardingItemParameters: 0=hrs,1=hzr
overwrite: true
failover: true
3.用两个窗口启动主类的运行结果
3.1启动类
package cn.hrs.tools.demo.elasticjob;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
/**
* @author huangrusheng
* @version 1.0
* @date 2021/6/6 11:04
*/
@SpringBootApplication
public class ElasticJobApplication {
public static void main(String args[]){
new SpringApplicationBuilder(ElasticJobApplication.class).web(WebApplicationType.NONE)
.run(args);
}
}
3.2运行日志