elastic-job

一、工作原理

1.1zookeeper

  • Elastic-Job依赖ZooKeeper完成对执行任务信息的存储(如任务名称、任务参与实例、任务执行策略等)

  • Elastic-Job依赖ZooKeeper实现选举机制,在任务执行实例数量变化时(如在快速上手中的启动新实例或停止实例),会触发选举机制来决定让哪个实例去执行该任务。

ZooKeeper是一个分布式一致性协调服务,它是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。

咱们可以把ZooKeeper想象为一个特殊的数据库,它维护着一个类似文件系统的树形数据结构,ZooKeeper的客户端(如Elastic-Job任务执行实例)可以对数据进行存取:

每个子目录项如 /app1都被称作为 znode(目录节点),和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。

ZooKeeper为什么称之为一致性协调服务呢?因为ZooKeeper拥有数据监听通知机制,客户端注册监听它关心的znode,当znode发生变化(数据改变、被删除、子目录节点增加删除)时,ZooKeeper会通知所有客户端。简单来说就是,当分布式系统的若干个服务都关心一个数据时,当这个数据发生改变,这些服务都能够得知,那么这些服务就针对此数据达成了一致。

应用场景思考,使用ZooKeeper管理分布式配置项的机制:
假设我们的程序是分布式部署在多台机器上,如果我们要改变程序的配置文件,需要逐台机器去修改,非常麻烦,现在把这些配置全部放到zookeeper上去,保存在zookeeper 的某个目录节点中,然后所有相关应用程序作为ZooKeeper的客户端对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 ZooKeeper的通知,从而获取新的配置信息应用到系统中。

1.2Elastic-Job工作原理

1.2.1Elastic-Job整体架构

App:应用程序,内部包含任务执行业务逻辑Elastic-Job-Lite组件,其中执行任务需要实现ElasticJob接口完成与Elastic-Job-Lite组件的集成,并进行任务的相关配置。应用程序可启动多个实例,也就出现了多个任务执行实例。

Elastic-Job-Lite:Elastic-Job-Lite定位为轻量级无中心化解决方案,使用jar包的形式提供分布式任务的协调服务,此组件负责任务的调度,并产生日志及任务调度记录。

无中心化,是指没有调度中心这一概念,每个运行在集群中的作业服务器都是对等的,各个作业节点是自治的、平等的、节点之间通过注册中心进行分布式协调。

Registry:以Zookeeper作为Elastic-Job的注册中心组件,存储了执行任务的相关信息。同时,Elastic-Job利用该组件进行执行任务实例的选举。

Console:Elastic-Job提供了运维平台,它通过读取Zookeeper数据展现任务执行状态,或更新Zookeeper数据修改全局配置。通过Elastic-Job-Lite组件产生的数据来查看任务执行历史记录。应用程序在启动时,在其内嵌的Elastic-Job-Lite组件会向Zookeeper注册该实例的信息,并触发选举(此时可能已经启动了该应用程序的其他实例),从众多实例中选举出一个Leader,让其执行任务。当到达任务执行时间时,Elastic-Job-Lite组件会调用由应用程序实现的任务业务逻辑,任务执行后会产生任务执行记录。当应用程序的某一个实例宕机时,Zookeeper组件会感知到并重新触发leader选举。

1.3一个分布式任务的demo

模拟定时任务备份文件

1.3.1依赖

<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>
    <version>1.18.0</version>
</dependency>

1.3.2文件类

package com.ms.elasticjob.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
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;
    }
}

1.3.3编写定时任务类

此任务在每次执行时获取一定数目的文件,进行备份处理,由File实体类的backedUp属性来标识该文件是否已备份。

package com.ms.elasticjob.job;

import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.ms.elasticjob.entity.FileCustom;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class FileBackupJob implements SimpleJob {

    //每次任务执行要备份文件的数量
    private final int FETCH_SIZE = 1;

    public static List<FileCustom> files = new ArrayList<>();

    @Override
    public void execute(ShardingContext shardingContext) {
        //获取未备份的文件
        List<FileCustom> fileCustoms = fetchUnBackupFiles(FETCH_SIZE);

        //文件备份
        backupFiles(fileCustoms);
    }

    //获取未备份的文件
    public List<FileCustom> fetchUnBackupFiles(int count) {
        LinkedList<FileCustom> list = new LinkedList<>();
        int num = 0;
        for (FileCustom file : files) {
            if (num >= count) {
                break;
            }
            if (!file.getBackedUp()) {
                list.add(file);
                num++;
            }
        }
        System.out.printf("获取文件个数:%s %n",num);
        return list;
    }

    /**
     * 备份文件
     *
     * @param files
     */
    public void backupFiles(List<FileCustom> files) {
        for (FileCustom file : files) {
            //标记文件数据为已备份
            file.setBackedUp(Boolean.TRUE);
            System.out.printf("已备份文件:%s 文件类型:%s %n",file.getName(),file.getType());
        }
    }
}

1.3.4启动类

package com.ms.elasticjob.job;

import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.lite.api.JobScheduler;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import com.ms.elasticjob.entity.FileCustom;

public class JobMain {
    //zookeeper端口
    private static final int ZOOKEEPER_PORT = 2181;
    //zookeeper链接字符串 localhost:2181
    private static final String ZOOKEEPER_CONNECTION_STRING = "192.168.232.130:" + ZOOKEEPER_PORT;
    //定时任务命名空间
    private static final String JOB_NAMESPACE = "elastic‐job‐example‐java";

    //启动任务
    public static void main(String[] args) {
        //生成测试文件
        generateTestFiles();
        //配置zookeeper
        CoordinatorRegistryCenter registryCenter = setUpRegistryCenter();
        //启动任务
        startJob(registryCenter);
    }

    //注册中心配置
    private static CoordinatorRegistryCenter setUpRegistryCenter() {
        //注册中心配置
        ZookeeperConfiguration zookeeperConfiguration = new
                ZookeeperConfiguration(ZOOKEEPER_CONNECTION_STRING, JOB_NAMESPACE);
        //减少zk的超时时间
        zookeeperConfiguration.setSessionTimeoutMilliseconds(100);
        //创建注册中心
        CoordinatorRegistryCenter registryCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
        registryCenter.init();
        return registryCenter;
    }

    //配置并启动任务
    private static void startJob(CoordinatorRegistryCenter registryCenter) {
        //创建JobCoreConfiguration
        JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration.newBuilder("files‐job",
                        "0/3 * * * * ?", 1)//分片数
                .build();
        //创建SimpleJobConfiguration
        SimpleJobConfiguration simpleJobConfiguration = new SimpleJobConfiguration(jobCoreConfiguration, FileBackupJob.class.getCanonicalName());
        //启动任务
        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), "vedio", "content" + (i + 40)));
        }
    }

}

1.3.5测试

当shardingTotalCount(分片)为1时,同时启动两个线程去执行任务,只会有一个线程会成功执行,如果其中一个挂了,另一个个就会接管

当shardingTotalCount(分片)为n时,任务会被分为n片,每个线程会分摊一个分片,运行结束,继续拿去其他分片,如果某个线程挂了,其他某个线程会接管分片

1.4Elastic-Job任务信息的保存

Elastic-Job使用ZooKeeper完成对任务信息的存取,任务执行实例作为ZooKeeper客户端对其znode操作,任务信息保存在znode中。

使用zoolnspector查看zookeeper节点

config结点内容

{
  "jobName": "files鈥恓ob",
  "jobClass": "com.ms.elasticjob.job.FileBackupJob",
  "jobType": "SIMPLE",
  "cron": "0/3 * * * * ?",
  "shardingTotalCount": 1,
  "shardingItemParameters": "",
  "jobParameter": "",
  "failover": false,
  "misfire": true,
  "description": "",
  "jobProperties": {
    "job_exception_handler": "com.dangdang.ddframe.job.executor.handler.impl.DefaultJobExceptionHandler",
    "executor_service_handler": "com.dangdang.ddframe.job.executor.handler.impl.DefaultExecutorServiceHandler"
  },
  "monitorExecution": true,
  "maxTimeDiffSeconds": -1,
  "monitorPort": -1,
  "jobShardingStrategyClass": "",
  "reconcileIntervalMinutes": 10,
  "disabled": false,
  "overwrite": true
}

节点记录了任务的配置信息,包含执行类,cron表达式,分片算法类,分片数量,分片参数。默认状态下,如果你修改了Job的配置比如cron表达式,分片数量等是不会更新到zookeeper上去的,需要把LiteJobConfifiguration的参数overwrite修改成true,或者删除zk的结点再启动作业重新创建。

instances节点:同一个Job下的elastic-job的部署实例。一台机器上可以启动多个Job实例,也就是Jar包。instances的命名是[IP+@-@+PID]

leader节点: 任务实例的主节点信息,通过zookeeper的主节点选举,选出来的主节点信息。下面的子节点分为election,sharding和failover三个子节点。分别用于主节点选举,分片和失效转移处理。election下面的instance节点显式了当前主节点的实例ID:jobInstanceId。latch节点也是一个永久节点用于选举时候的实现分布式锁。sharding节点下面有一个临时节点necessary,是否需要重新分片的标记,如果分片总数变化或任务实例节点上下

线,以及主节点选举,都会触发设置重分片标记,主节点会进行分片计算。

sharding节点: 任务的分片信息,子节点是分片项序号,从零开始,至分片总数减一。从这个节点可以看出哪个分片在哪个实例上运行

1.5Elastic-Job任务执行实例选举

Elastic-Job使用ZooKeeper实现任务执行实例选举,若要使用ZooKeeper完成选举,就需要了解ZooKeeper的znode类型了,ZooKeeper有四种类型的znode,客户端在创建znode时可以指定:

  • PERSISTENT-持久化目录节点

客户端创建该类型znode,此客户端与ZooKeeper断开连接后该节点依旧存在,如果创建了重复的key,比如/data,第二次创建会失败。

  • PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点

客户端与ZooKeeper断开连接后该节点依旧存在,允许重复创建相同key,Zookeeper给该节点名称进行顺序编号,如zk会在后面加一串数字比如 /data/data0000000001,如果重复创建,会创建一个/data/data0000000002节点(一直往后加1)

  • EPHEMERAL-临时目录节点

客户端与ZooKeeper断开连接后,该节点被删除,不允许重复创建相同key。

  • EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点

客户端与ZooKeeper断开连接后,该节点被删除,允许重复创建相同key,依然采取顺序编号机制。

实例选举实现过程分析

每个Elastic-Job的任务执行实例作为ZooKeeper的客户端来操作ZooKeeper的znode

1)任意一个实例启动时首先创建一个 /server 的PERSISTENT节点

2)多个实例同时创建 /server/leader EPHEMERAL子节点

3)/server/leader子节点只能创建一个,后创建的会失败。创建成功的实例被选为leader节点 ,用来执行任务。

4)所有任务实例监听 /server/leader 的变化,一旦节点被删除,就重新进行选举,抢占式地创建 /server/leader节点,谁创建成功谁就是leader。

二、整合springboot

<dependency>
    <groupId>com.dangdang</groupId>
    <artifactId>elastic-job-lite-spring</artifactId>
    <version>2.1.5</version>
</dependency>

2.1zookeeper注册中心

package com.ms.elasticjob.withboot.config;

import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ElasticJobRegistryCenterConfig {

    //zookeeper端口
    private static final int ZOOKEEPER_PORT = 2181;
    //zookeeper链接字符串 localhost:2181
    private static final String ZOOKEEPER_CONNECTION_STRING = "192.168.232.130:" + ZOOKEEPER_PORT;
    //定时任务命名空间
    private static final String JOB_NAMESPACE = "elastic‐job‐example‐java";

    //注册中心配置
    @Bean(initMethod = "init")
    private static CoordinatorRegistryCenter setUpRegistryCenter() {
        //注册中心配置
        ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration(ZOOKEEPER_CONNECTION_STRING, JOB_NAMESPACE);
        //减少zk的超时时间
        zookeeperConfiguration.setSessionTimeoutMilliseconds(100);
        //创建注册中心
        CoordinatorRegistryCenter registryCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
        return registryCenter;
    }

}

2.2Elastic-Job配置类

package com.ms.elasticjob.withboot.config;

import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.JobRootConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.lite.spring.api.SpringJobScheduler;
import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import com.ms.elasticjob.withboot.job.FileBackupJob;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

/**
 * <p>Project:我的代码-EalsticJobConfig
 * <p>Powered by ms on 2023-02-10 22:39:30
 *
 * @author ms
 * @version 1.0
 * @since 1.8
 */
@Configuration
public class ElasticJobConfig {

    @Autowired
    private CoordinatorRegistryCenter registryCenter;

    @Autowired
    private FileBackupJob fileBackupJob;

    /**
     * 配置任务详细信息
     *
     * @param jobClass               任务执行类
     * @param cron                   执行策略
     * @param shardingTotalCount     分片数量
     * @param shardingItemParameters 分片个性化参数
     * @return
     */
    private LiteJobConfiguration createJobConfiguration(final Class<? extends SimpleJob> jobClass,
                                                        final String cron,
                                                        final int shardingTotalCount,
                                                        final String shardingItemParameters) {
        // 定义作业核心配置
        JobCoreConfiguration.Builder simpleCoreConfigBuilder = JobCoreConfiguration.newBuilder(jobClass.getName(), cron, shardingTotalCount);
        if (!StringUtils.isEmpty(shardingItemParameters)) {
            simpleCoreConfigBuilder.shardingItemParameters(shardingItemParameters);
        }
        JobCoreConfiguration jobCoreConfiguration = simpleCoreConfigBuilder.build();
        // 定义SIMPLE类型配置
        SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(jobCoreConfiguration, jobClass.getCanonicalName());
        // 定义Lite作业根配置
        JobRootConfiguration simpleJobRootConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).overwrite(true).build();
        return (LiteJobConfiguration) simpleJobRootConfig;
    }

    /**
     * 任务启动
     *
     * @return
     */
    @Bean(initMethod = "init")
    public SpringJobScheduler initSimpleElasticJob() {
        SimpleJob job1 = fileBackupJob;
        SpringJobScheduler jobScheduler = new SpringJobScheduler(job1,
                registryCenter,
                createJobConfiguration(job1.getClass(), "0/3 * * * * ?",
                        1,
                        null));
        return jobScheduler;
    }
}

2.3任务类

使用1.3.3中的任务类计科

三、作业分片

3.1分片概念

作业分片是指任务的分布式执行,需要将一个任务拆分为多个独立的任务项,然后由分布式的应用实例分别执行某一个或几个分片项。

例如:1.3demo中文件备份的例子,现有2台服务器,每台服务器分别跑一个应用实例。为了快速的执行作业,那么可以将作业分成4片,每个应用实例个执行2片。作业遍历数据的逻辑应为:实例1查找text和image类型文件执行备份;实例2查找radio和video类型文件执行备份。

如果由于服务器扩容应用实例数量增加为4,则作业遍历数据的逻辑应为:4个实例分别处理text、image、radio、video类型的文件。可以看到,通过对任务合理的分片化,从而达到任务并行处理的效果,最大限度的提高执行作业的吞吐量。

分片项与业务处理解耦

Elastic-Job并不直接提供数据处理的功能,框架只会将分片项分配至各个运行中的作业服务器,开发者需要自行处理分片项与真实数据的对应关系。

最大限度利用资源

将分片项设置为大于服务器的数量,最好是大于服务器倍数的数量,作业将会合理的利用分布式资源,动态的分配分片项。

例如:3台服务器,分成10片,则分片项分配结果为服务器A=0,1,2;服务器B=3,4,5;服务器C=6,7,8,9。 如果服务器C崩溃,则分片项分配结果为服务器A=0,1,2,3,4;服务器B=5,6,7,8,9。在不丢失分片项的情况下,最大限度的利用现有资源提高吞吐量。

3.2代码实现

3.3作业配置说明

3.3.1注册中心配置

ZookeeperConfifiguration属性详细说明

属性名

类型

构造器注入

缺省值

描述

serverLists

String

连接Zookeeper服务器的列表 包括IP地址和端口号,多个地址用逗号分隔 如: host1:2181,host2:2181

namespace

String

Zookeeper的命名空间

baseSleepTimeMilliseconds

int

1000

等待重试的间隔时间的初始值 单位:毫秒

maxSleepTimeMilliseconds

String

3000

等待重试的间隔时间的最大值 单位:毫秒

maxRetries

String

3

最大重试次数

sessionTimeoutMilliseconds

boolean

60000

会话超时时间 单位:毫秒

connectionTimeoutMilliseconds

boolean

15000

连接超时时间 单位:毫秒

digest

String

连接Zookeeper的权限令牌 缺省为不需要权限验证

3.3.2作业配置

作业配置分为3级,分别是JobCoreConfifiguration,JobTypeConfifiguration和LiteJobConfifiguration。

LiteJobConfifiguration使用JobTypeConfifiguration,JobTypeConfifiguration使用JobCoreConfifiguration,层层嵌套。

JobTypeConfifiguration根据不同实现类型分为SimpleJobConfifiguration,DataflflowJobConfifiguration和ScriptJobConfifiguration。

属性名

类型

构造器注入

缺省值

描述

jobName

String

作业名称

cron

String

cron表达式,用于控制作业触发时间

shardingTotalCount

int

作业分片总数

shardingItemParameters

String

分片序列号和参数用等号分隔,多个键值对用逗号分隔 分片序列号从0开始,不可大于或等于作业分片总数 如: 0=a,1=b,2=c

jobParameter

String

作业自定义参数 作业自定义参数,可通过传递该参数为作业调度的业务方法传参,用于实现带参数的作业 例:每次获取的数据量、作业实例从数据库读取的主键等

failover

boolean

false

是否开启任务执行失效转移,开启表示如果作业在一次任务执行中途宕机,允许将该次未完成的任务在另一作业节点上补偿执行

misfire

boolean

true

是否开启错过任务重新执行

description

String

作业描述信息

jobProperties

Enum

配置jobProperties定义的枚举控制Elastic-Job的实现细节

JOB_EXCEPTION_HANDLER用于扩展异常处理类

EXECUTOR_SERVICE_HANDLER用于扩展作业处理线程池类

3.3.3作业分片策略

AverageAllocationJobShardingStrategy

全路径:com.dangdang.ddframe.job.lite.api.strategy.impl.AverageAllocationJobShardingStrategy

策略说明:

基于平均分配算法的分片策略,也是默认的分片策略。

如果分片不能整除,则不能整除的多余分片将依次追加到序号小的服务器。如:

如果有3台服务器,分成9片,则每台服务器分到的分片是:1=[0,1,2], 2=[3,4,5], 3=[6,7,8]

如果有3台服务器,分成8片,则每台服务器分到的分片是:1=[0,1,6], 2=[2,3,7], 3=[4,5]

如果有3台服务器,分成10片,则每台服务器分到的分片是:1=[0,1,2,9], 2=[3,4,5], 3=[6,7,8]

OdevitySortByNameJobShardingStrategy

全路径:com.dangdang.ddframe.job.lite.api.strategy.impl.OdevitySortByNameJobShardingStrategy

策略说明:

根据作业名的哈希值奇偶数决定IP升降序算法的分片策略。

作业名的哈希值为奇数则IP升序。作业名的哈希值为偶数则IP降序。

用于不同的作业平均分配负载至不同的服务器。

AverageAllocationJobShardingStrategy的缺点是,一旦分片数小于作业服务器数,作业将永远分配至IP地址靠前的服务器,导致IP地址靠后的服务器空闲。而OdevitySortByNameJobShardingStrategy则可以根据作业名称重新分配服务器负载。

如:

如果有3台服务器,分成2片,作业名称的哈希值为奇数,则每台服务器分到的分片是:1=[0], 2=[1], 3=[]

如果有3台服务器,分成2片,作业名称的哈希值为偶数,则每台服务器分到的分片是:3=[0], 2=[1], 1=[]

RotateServerByNameJobShardingStrategy

全路径:com.dangdang.ddframe.job.lite.api.strategy.impl.RotateServerByNameJobShardingStrategy

策略说明:

根据作业名的哈希值对服务器列表进行轮转的分片策略。

配置分片策略

与配置通常的作业属性相同,在spring命名空间或者JobConfifiguration中配置jobShardingStrategyClass属性,属性值是作业分片策略类的全路径。

JobRootConfiguration simpleJobRootConfig = LiteJobConfiguration
                .newBuilder(simpleJobConfig)
                .overwrite(true)
                .jobShardingStrategyClass("com.dangdang.ddframe.job.lite.api.strategy.impl.OdevitySortByNameJobShardingStrategy")
                .build();

四、Dataflow类型定时任务

Dataflow类型的定时任务需实现DataflowJob接口,该接口提供2个方法可供覆盖,分别用于抓取(fetchData)和处理(processData)数据。

Dataflow类型用于处理数据流,它和SimpleJob不同,它以数据流的方式执行,调用fetchData抓取数据,直到抓取不到数据才停止作业。

4.1让任务类实现DateflowJob接口

package com.ms.elasticjob.withboot.job;

import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.dataflow.DataflowJob;
import com.ms.elasticjob.withboot.entity.FileCustom;

import java.util.List;

public class FileBackupJobDataflow implements DataflowJob<FileCustom> {

    //抓取数据
    @Override
    public List<FileCustom> fetchData(ShardingContext shardingContext) {
        return null;
    }

    //处理数据
    @Override
    public void processData(ShardingContext shardingContext, List<FileCustom> list) {

    }
}

五、时间追踪

项目启动后会在数据库中自动添加两张表

JOB_EXECUTION_LOG表

JOB_STATUS_TRACE_LOG表

JOB_EXECUTION_LOG记录每次作业的执行历史。分为两个步骤:

1. 作业开始执行时向数据库插入数据,除failure_cause和complete_time外的其他字段均不为空。

2. 作业完成执行时向数据库更新数据,更新is_success, complete_time和failure_cause(如果作业执行失败)。

JOB_STATUS_TRACE_LOG记录作业状态变更痕迹表。可通过每次作业运行的task_id查询作业状态变化的生命周期和运行轨迹。

六、运维

elastic-job中提供了一个elastic-job-lite-console控制台

设计理念

1. 本控制台和Elastic Job并无直接关系,是通过读取Elastic Job的注册中心数据展现作业状态,或更新注册中心数据修改全局配置。

2. 控制台只能控制作业本身是否运行,但不能控制作业进程的启停,因为控制台和作业本身服务器是完全分布式的,控制台并不能控制作业服务器。

主要功能

1. 查看作业以及服务器状态

2. 快捷的修改以及删除作业设置

3. 启用和禁用作业

4. 跨注册中心查看作业

5. 查看作业运行轨迹和运行状态

不支持项添加作业

下载地址

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值