分布式任务调度平台

一、任务调度概述 

1.什么是任务调度--定时job 在什么时间进行执行代码任务
任务调度场景:定时检查红包过期
2.java实现定时任务有几种?
        Thread.sleep
TimerTask  util包下
线程池,可定时线程
Quartz定时任务调度框架

springboot 内置定时任务调度

/**
 * 使用多线程方式实现定时job  最简单版定时任务调度
 * Created by yz on 2018/04/07.
 */
public class ThreadJob {
    static int count = 0;
    public static void main(String[] args) {
        // 实现定时认为,特征,一直在运行,到时间执行
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 监听任务调度
                while (true){
                    // 每隔一秒时间实现定时
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("我是第"+(count++));
                }
            }
        }).start();
    }
}
import java.util.Timer;
import java.util.TimerTask;

/**
 * timerTask 实现定时job
 * Created by yz on 2018/04/07.
 */
public class TimerTaskJob {
    static int count = 0;
    public static void main(String[] args) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                // 执行任务代码
                System.out.println("我是第"+(count++));
            }
        };

        Timer timer = new Timer();
        // 天数 0每天
        long delay = 0;
        // 毫秒数
        long period = 1000;
        timer.scheduleAtFixedRate(timerTask,delay,period);
    }
}
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 线程池实现定时job
 * 线程池四种实现,可缓存,可定长,可定时及单线程线程池
 * Created by yz on 2018/04/07.
 */
public class ThreadPoolJob {
    static int count = 0;
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("我是第"+(count++));
            }
        };
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        // 参数2:首次执行的延时时间,参数2:定时执行的间隔时间
        service.scheduleAtFixedRate(runnable,1,1, TimeUnit.SECONDS);
    }
}
 
二、使用Quartz实现定时调度

pom.xml

<!-- quartz-->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.2.1</version>
</dependency>
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;

/**
 * Quartz 实现定时job
 * Created by yz on 2018/04/07.
 */
public class QuartzJob implements Job{

    // 执行任务调度方法
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("quartz QuartzJob date:"+ new Date().getTime());
    }
}
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.Date;

/**
 * Created by yz on 2018/04/07.
 */
public class TestQuartzJob {
    public static void main(String[] args) throws SchedulerException {
        // 1.创建scheduler工厂
        SchedulerFactory sf = new StdSchedulerFactory();
        // 2.从工厂中获取调度器实例
        Scheduler scheduler = sf.getScheduler();
        // 3.创建JobDetail
        JobDetail jobDetail = JobBuilder.newJob(QuartzJob.class)
                .withDescription("this is a ram job") // job的描述
                .withIdentity("ramJob", "ramGroup") // job的name和group
                .build();
        // 任务运行的时间,
        long time = System.currentTimeMillis()+3*1000L; // 3秒后启动任务
        Date statTime = new Date(time);

        // 4.创建Trigger 表达式规则
        Trigger trigger = TriggerBuilder.newTrigger()
                .withDescription("")
                .withIdentity("ramTrigger", "ramTrigger")
                .startAt(statTime)
                .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))  // 两秒执行一次
                .build();

        // 5.注册任务和定时器
        scheduler.scheduleJob(jobDetail,trigger);
        // 6.启动调度器
        scheduler.start();
    }
}
 

三、分布JOB如何解决幂等性

集群情况下,实现定时job会产生什么问题?
假如两台服务器都有QuartzJob,服务器启动起来会执行两次。

分布式job如何解决幂等性?
1.使用分布式锁(zk、redis) 保证只有一台服务器执行job
2.使用配置文件方式,配置文件开关 start=true 执行 或则好 start=false 不执行,打两个不同war包,这样集群就没用了。
3.使用数据库唯一标识 ,必须插入一条数据,效率低,不用。

传统任务调度 缺点:
1.没有补偿机制 2.不支持集群 3.不支持路由策略(类似负载均衡,分发到哪个job执行)4.统计,哪些job失败了
5.job管理平台 6.报警邮箱,job失败后重试n多次还不行,发送报警。7.状态监控

-- 分布式任务调度平台
解决传统任务调度缺点。
人性化,比如修改任务时间,不需要修改代码、不需要重新发版.

 
四、XXL-JOB环境概述

免费开源
http://www.xuxueli.com/page/projects.html
源码地址:https://github.com/xuxueli/xxl-job

 
五、分布式任务调度平台执行原理

分布式job调度平台原理:任何job先在任务调度平台执行,再由任务调度平台路由到实际job服务器。保证了job幂等性。
使用:

首先创建一个数据库及表结构:执行 tables_xxl_job.sql 

启动xxl-job-admin



 

六、任务调度平台执行器运行

执行器管理-新增执行器

扫描二维码关注公众号,回复: 3983859 查看本文章


任务管理-新增任务



查看调度日志:


启动springboot job项目,打印

Hello Job---->9999

 

七、任务调度平台路由策略



猜你喜欢

转载自blog.csdn.net/yz2015/article/details/79840259