springcloud如何使用分布式调度 elasticjob + zookeeper(分片和Dataflow)

配置

pom.xml

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

application.yml

  • 这里的zookeeper设置是自定义的,为了给类通过${}使用这里的属性值,解决硬编码问题
zookeeper:
  host: localhost:2181
  namespace:  springboot-elastic-job-demo
server:
  port: 8082

准备工作

数据库

在这里插入图片描述

实体类

@Data
public class FileCustom {
    //唯一标识
    private Long id;
    //文件名
    private String name;
    //文件类型
    private String type;
    //文件内容
    private String content;
    //是否已备份
    private Boolean backedUp = false;
    public FileCustom(){}
    public FileCustom(Long id, String name, String type, String content){
        this.id = id;
        this.name = name;
        this.type = type;
        this.content = content;
    }
}

mapper部分

在这里插入图片描述

开搞

  • 主要讲解以下类
    在这里插入图片描述

ZookeeperConfig

  • 配置zookeeper服务,前提必须启动zookeeper服务
@Configuration
public class ZookeeperConfig {

    @Bean
    private static CoordinatorRegistryCenter createRegistryCenter(@Value("${zookeeper.host}") String host, @Value("${zookeeper.namespace}") String namespace) {
        //配置zk地址,调度任务的组名
        ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration(host, namespace);
        zookeeperConfiguration.setSessionTimeoutMilliseconds(100);
        CoordinatorRegistryCenter regCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
        regCenter.init();
        return regCenter;
    }
}

JobConfiguration(重点)

  • 任务配置类,分布式调度初始化方法在这里定义,启动启动类则开始初始化(开始定时操作)
  • 注意:初始化方法的传入参数要传任务类,createJobConfiguration方法的第一个参数也要传任务类类型
  • 此演示注释掉的部分则是Dataflow的方式调度
@Configuration
public class JobConfiguration {

    @Autowired
    private CoordinatorRegistryCenter coordinatorRegistryCenter;
    @Autowired
    private DataSource dataSource;


    @Bean(initMethod = "init")
    public SpringJobScheduler springJobScheduler(FileCustomJob fileCustom) {
        //增加任务事件追踪配置
        JobEventConfiguration jobEventConfiguration = new JobEventRdbConfiguration(dataSource);
//        1 执行逻辑操作的类  2 zookeeper配置类的方法  3 定时多久执行业务操作的方法
        return new SpringJobScheduler(fileCustom, coordinatorRegistryCenter, createJobConfiguration(FileCustomJob.class, "0/10 * * * * ?",
                4, "0=text,1=radio,2=vedio,3=image",true),jobEventConfiguration);
    }

//    @Bean(initMethod = "init")
//    public SpringJobScheduler springJobScheduler(MyDataflowJob fileCustom) {
//        //增加任务事件追踪配置
//        JobEventConfiguration jobEventConfiguration = new JobEventRdbConfiguration(dataSource);
        1 执行逻辑操作的类  2 zookeeper配置类的方法  3 定时多久执行业务操作的方法
//        return new SpringJobScheduler(fileCustom, coordinatorRegistryCenter, createJobConfiguration(MyDataflowJob.class, "0/10 * * * * ?",
//                1, null,true),jobEventConfiguration);
//    }

    private static LiteJobConfiguration createJobConfiguration(Class clz, String cron, int shardingCount, String shardingParam, boolean isDataflow) {
        // 定义作业核心配置
//        1 任务名称保证唯一 2 cron表达式 3分片参数
        JobCoreConfiguration.Builder builder = JobCoreConfiguration.newBuilder(clz.getSimpleName(), cron, shardingCount);
        if (!StringUtils.isEmpty(shardingParam)) {
//            设置分片参数
            builder.shardingItemParameters(shardingParam);
        }
        JobCoreConfiguration simpleCoreConfig = builder.build();

        JobTypeConfiguration jobTypeConfiguration = null;//
        if (isDataflow) {
            jobTypeConfiguration = new DataflowJobConfiguration(simpleCoreConfig, clz.getCanonicalName(), true);
        } else {
            // 定义SIMPLE类型配置
            jobTypeConfiguration = new SimpleJobConfiguration(simpleCoreConfig, clz.getCanonicalName());
        }

        // 定义Lite作业根配置
        LiteJobConfiguration simpleJobRootConfig = LiteJobConfiguration.newBuilder(jobTypeConfiguration).overwrite(true).build();
        return simpleJobRootConfig;
    }



}

分片调度

介绍

  • 作业分片是指任务的分布式执行,需要将一个任务拆分为多个独立的任务项,然后由分布式的应用实例分别执行某一个或者几个分布项。例如:Elastic-Job快速入门中文件备份的案例,现有两台服务器,每台服务器分别跑一个应用实例。为了快速执行作业,那么可以讲任务分成4片,每个应用实例都执行两片。作业遍历数据逻辑应为:实例1查找text和image类型文件执行备份,实例2查找radio和vedio类型文件执行备份。如果由于服务器拓容应用实例数量增加为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.在不丢失分片项的情况下,最大限度利用现有的资源提高吞吐量.

定义分片调度任务类

FileCustomJob类,分片任务类要实现SimpleJob接口

@Component
public class FileCustomJob implements SimpleJob {

    @Autowired
    private FileCustomMapper fileCustomMapper;

    //执行我们定时任务, 比如每隔30分钟就会执行一次execute方法
    public void execute(ShardingContext shardingContext) {
//            doWork(shardingContext.getShardingParameter());
        System.out.println("分片参数: "+shardingContext.getShardingParameter());
    }

    private void doWork(String shardingParam) {
//        把数据库表中backenUp = 0的数据查询出来
        List<FileCustom> fileCustoms =fileCustomMapper.selectByType(shardingParam);
        System.out.println("要备份的数据个数为:"+fileCustoms.size());
        //        把状态改成1
        for (FileCustom fileCustom : fileCustoms){
            changStatus(fileCustom);
        }
    }

    private void changStatus(FileCustom fileCustom) {
        System.out.println("要备份数据的id:"+fileCustom.getId()+" 要备份数据的类型:"+fileCustom.getType());
        try {
                Thread.sleep(1000);
        }catch (Exception e){
                e.printStackTrace();
        }
        fileCustomMapper.changStatus(fileCustom.getId(),1);
    }
}

Dataflow调度

介绍

  • Dataflow类型的定时任务需要实现Dataflowjob接口,该接口提供2个方法供覆盖,分别用于抓取(fetchData)和处理(processData)数据,我们继续对例子进行改造。

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

定义Dataflow调度任务类

  • 实现DataflowJob<>接口,<> 里面存放要被调度使用的实体类
@Component
public class MyDataflowJob implements DataflowJob<FileCustom> {

    @Autowired
    private FileCustomMapper fileCustomMapper;

    /**
     * 抓取数据方法
     * @param shardingContext
     * 一次性抓取2条数据 把2条数据的backedUp 由0->1
     * @return
     */
    @Override
    public List<FileCustom> fetchData(ShardingContext shardingContext) {
        return fileCustomMapper.fetchData(2);
    }

    @Override
    public void processData(ShardingContext shardingContext, List<FileCustom> list) {
        System.out.println("要备份的数据个数为:"+list.size());
        //        把状态改成1
        for (FileCustom fileCustom : list){
            changStatus(fileCustom);
        }
    }

    private void changStatus(FileCustom fileCustom) {
        System.out.println("要备份数据的id:"+fileCustom.getId()+" 要备份数据的类型:"+fileCustom.getType());
        try {
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }
        fileCustomMapper.changStatus(fileCustom.getId(),1);
    }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值