1.概述
任务调度:是指系统在特定的时间去执行任务的过程
Quartz:是一个功能强大的任务调度框架,它可以满足更多更复杂的调度需求,支持按时间间隔调度和按日历调度,通过设置CronTrigger表达式(包括:秒分时日月周年)进行任务调度
Cron表达式推荐文章:https://www.cnblogs.com/sunjie9606/archive/2012/03/15/2397626.html
分布式:能把系统进行拆分并部署到多台服务器上的系统
分布式调度:在分布式系统中的任务调度
2.Elastic-Job快速入门实例
(1)创建maven工程elastic-job-quickstart,并导入以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.dangdang/elastic-job-lite-core -->
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-core</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
(2)编写定时任务类
public class FileBackupJob implements SimpleJob {
//每次任务执行要备份文件的数量
private final int FETCH_SIZE = 1;
//文件列表(模拟)
public static List<FileCustom> files = new ArrayList<>();
//任务执行代码逻辑
@Override
public void execute(ShardingContext shardingContext) {
System.out.println("作业分片:"+shardingContext.getShardingItem());
//获取未备份的文件
List<FileCustom> fileCustoms = fetchUnBackupFiles(FETCH_SIZE);
//进行文件备份
backupFiles(fileCustoms);
}
/**
* 获取未备份的文件
* @param count 文件数量
* @return
*/
public List<FileCustom> fetchUnBackupFiles(int count){
//获取的文件列表
List<FileCustom> fileCustoms = new ArrayList<>();
int num=0;
for(FileCustom fileCustom:files){
if(num >=count){
break;
}
if(!fileCustom.getBackedUp()){
fileCustoms.add(fileCustom);
num ++;
}
}
System.out.printf("time:%s,获取文件%d个\n", LocalDateTime.now(),num);
return fileCustoms;
}
/**
* 文件备份
* @param files
*/
public void backupFiles(List<FileCustom> files){
for(FileCustom fileCustom:files){
fileCustom.setBackedUp(true);
System.out.printf("time:%s,备份文件,名称:%s,类型:%s\n", LocalDateTime.now(),fileCustom.getName(),fileCustom.getType());
}
}
}
(3)文件实体类
@Data
public class FileCustom {
/**
* 标识
*/
private String id;
/**
* 文件名
*/
private String name;
/**
* 文件类型,如text、image、radio、vedio
*/
private String type;
/**
* 文件内容
*/
private String content;
/**
* 是否已备份
*/
private Boolean backedUp = false;
public FileCustom(String id,String name,String type,String content){
this.id = id;
this.name = name;
this.type = type;
this.content = content;
}
}
(4)启动任务类
public class JobMain {
//zookeeper端口
private static final int ZOOKEEPER_PORT = 2181;
//zookeeper链接字符串 localhost:2181
private static final String ZOOKEEPER_CONNECTION_STRING = "192.168.180.113:" + ZOOKEEPER_PORT;
//定时任务命名空间
private static final String JOB_NAMESPACE = "elastic-job-example-java";
//执行启动任务
public static void main(String[] args) {
//制造一些测试数据
generateTestFiles();
//配置注册中心
CoordinatorRegistryCenter registryCenter = setUpRegistryCenter();
//启动任务
startJob(registryCenter);
}
//zk的配置及创建注册中心
private static CoordinatorRegistryCenter setUpRegistryCenter(){
//zk的配置
ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration(ZOOKEEPER_CONNECTION_STRING, JOB_NAMESPACE);
//减少zk超时时间
zookeeperConfiguration.setSessionTimeoutMilliseconds(100);
//创建注册中心
CoordinatorRegistryCenter zookeeperRegistryCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
zookeeperRegistryCenter.init();
return zookeeperRegistryCenter;
}
//任务的配置和启动
private static void startJob(CoordinatorRegistryCenter registryCenter){
//String jobName 任务名称, String cron 调度表达式, int shardingTotalCount 作业分片数量
JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration.newBuilder("fiels-job", "0/3 * * * * ?", 3).build();
//创建SimpleJobConfiguration
SimpleJobConfiguration simpleJobConfiguration = new SimpleJobConfiguration(jobCoreConfiguration, FileBackupJob.class.getCanonicalName());
//创建new JobScheduler
new JobScheduler(registryCenter, LiteJobConfiguration.newBuilder(simpleJobConfiguration).overwrite(true).build()).init();
}
//制造一些测试数据
//生成测试文件
private static void generateTestFiles(){
for(int i=1;i<11;i++){
FileBackupJob.files.add(new FileCustom(String.valueOf(i+10),"文件"+(i+10),"text","content"+ (i+10)));
FileBackupJob.files.add(new FileCustom(String.valueOf(i+20),"文件"+(i+20),"image","content"+ (i+20)));
FileBackupJob.files.add(new FileCustom(String.valueOf(i+30),"文件"+(i+30),"radio","content"+ (i+30)));
FileBackupJob.files.add(new FileCustom(String.valueOf(i+40),"文件"+(i+40),"video","content"+ (i+40)));
}
System.out.println("生产测试数据完成");
}
}
3.Elastic-Job工作原理
Elastic-Job架构图:
Zookeeper作用:
(1)信息的存储
(2)实现选举机制
Zookeeper推荐文章:https://www.cnblogs.com/xinyonghu/p/11031729.html
4.作业分片
作业分片:把一个任务分散到不同的机器上运行,既可以解决单机计算能力上限的问题,也能降低部分任务失败对整体系统的影响
elastic-job作业分片:不直接提供数据处理的功能,框架只会将分片项分配至各个运行中的作业服务器,开发者需要自行处理分片项与真实数据的对应关系
elastic-job分片策略:基于平均分配算法的分片策略(默认分片策略)
5.Dataflow类型定时任务
Dataflow类型定时任务:用于处理数据流,需实现DataflowJob接口。该接口提供2个方法可供覆盖,分别用于抓取(fetchData)和处理(processData)数据
6.Elastic-Job高级
(1)事件追踪:通过事件订阅的方式处理调度过程的重要事件,用于查询、统计和监控
(2)运维推荐文章:https://blog.youkuaiyun.com/lovelong8808/article/details/80393290
(3)dump命令:使用Elastic-Job-Lite过程中可能会碰到一些分布式问题,导致作业运行不稳定,由于无法在生产环境调试,通过dump命令可以把作业内部相关信息dump出来,方便开发者debug分析
Elastic-Job官方手册:http://elasticjob.io/docs/elastic-job-lite/00-overview/