微服务架构-分布式解决方案-107:XXL-JOB原理的分析

1 xxl-job分布式任务调度平台演示

课题内容

  1. 传统的定时任务存在哪些缺陷
  2. 定时任务有哪些实现方案
  3. 基于XXL-JOB实现分布式任务调度
  4. XXL-JOB集群方案部署的原理

2 传统的定时任务存在哪些缺陷

传统的定时任务存在哪些缺陷?
1.定时任务代码和业务逻辑代码放入同一个jar中,如果定时任务挂了也会影响到业务逻辑,需要将定时任务和业务逻辑代码完全分开项目部署;
2.如果服务器集群的情况下,可能存在定时任务会重复触发执行;

3 集群中的定时任务如何保证执行幂等性

如何保证定时任务在集群中只会执行一个?

  1. 将定时任务代码单独部署一个jar包中,不参与业务逻辑服务器集群部署;
  2. 在jar中开启一个定时任务配置开关,判断是否需要将定时任务类加载到spring容器中;
  3. 使用分布式锁。项目启动中,只要谁能够拿到分布式锁,谁就能够将定时任务的配置类加载到spring容器中,否则不加载;
  4. 数据库中插入主键id,只要谁能够往数据库中插入一条相同的主键,插入成功就可以加载定时任务配置类;
    以上方案只适合小项目,不适合互联网级别项目
  5. 采用分布式任务调度平台框架

4 传统的定时任务的实现方案

传统定时任务的实现方案
多线程形式、timertask、线程池、springboot注解形式、quartz

Maven依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.11.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 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>
</dependencies>

1.基于多线程方式实现

public class ThreadJob {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try{
                        Thread.sleep(1000);
                        System.out.println("定时任务每隔1s触发");
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

2.TimerTask

public class TimerTaskDemo {
    public static void main(String[] args) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "定时任务触发");
            }
        };
        Timer timer = new Timer();
        // 天数
        long delay = 0;
        // 耗秒数
        long period = 1000;
        timer.scheduleAtFixedRate(timerTask, delay, period);
    }
}

3.线程池

public class ScheduledExecutorServiceDemo {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "定时任务触发..");
            }
        };
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        scheduledExecutorService.scheduleAtFixedRate(runnable, 1, 1, TimeUnit.SECONDS);
    }
}

4.SpringBoot注解形式

@Component
public class UserScheduled {
    @Scheduled(cron = "0/1 * * * * *")
    public void taskUserScheduled() {
        System.out.println("定时任务触发...");
    }
}
@SpringBootApplication
@EnableScheduling
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class);
    }
}

5.基于Quartz实现

public class QuartzTest {
    public static void main(String[] args) throws SchedulerException {
        //1.创建Scheduler的工厂
        SchedulerFactory sf = new StdSchedulerFactory();
        //2.从工厂中获取调度器实例
        Scheduler scheduler = sf.getScheduler();


        //3.创建JobDetail
        JobDetail jb = JobBuilder.newJob(MyJob.class)
                .withDescription("this is a ram job") //job的描述
                .withIdentity("ramJob", "ramGroup") //job 的name和group
                .build();

        //任务运行的时间,SimpleSchedle类型触发器有效
        long time = System.currentTimeMillis() + 3 * 1000L; //3秒后启动任务
        Date statTime = new Date(time);

        //4.创建Trigger
        //使用SimpleScheduleBuilder或者CronScheduleBuilder
        Trigger t = TriggerBuilder.newTrigger()
                .withDescription("")
                .withIdentity("ramTrigger", "ramTriggerGroup")
                //.withSchedule(SimpleScheduleBuilder.simpleSchedule())
                .startAt(statTime)  //默认当前时间启动
                .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) //两秒执行一次
                .build();

        //5.注册任务和定时器
        scheduler.scheduleJob(jb, t);

        //6.启动 调度器
        scheduler.start();
    }
}
public class MyJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
       System.out.println("quartz MyJob date:" + new Date().getTime());
   }
}

5 分布式任务调度平台实现原理

常用式任务调度框架
Xxl-job(推荐)、elasticjob、SpringAlibaba Cloud SchedulerX

设计分布式任务调度平台
定时任务的项目一定是集群部署,但是最终只会执行一台服务器;
为了能够提高定时任务集群执行的效率,一定是分片执行;

原理分析:

  1. 手动的将定时任务的项目(执行器)服务器ip和端口号统一存放到分布式任务调度平台的注册中心;
  2. 所有的定时任务触发规则,先在“分布式任务调度中心”先触发,再查询注册中心执行器集群地址,采用负载均衡的算法只会取一个地址;
  3. 获取该地址之后,再使用rpc远程调用该接口,通知它可以去触发定时任务。
    在这里插入图片描述
    一句话总结分布式任务调度平台的原理:
    1 将定时任务项目(执行器)服务ip和端口号统一注册到分布式任务调度平台中,触发定时任务的时候先走分布式任务调度中心;
    2 分布式任务调度中心获取执行器集群列表,采用负载均衡算法获取一个地址,采用rpc通知执行器执行定时任务。

6 构建XXL-JOBAdmin调度中心

XXL-JOB任务调度平台
官网:https://www.xuxueli.com/xxl-job/

XXL-Job Admin平台搭建 任务调度中心
1、官方下载XXL-Job Admin的源代码
2、导入xxl-job需要依赖的sql(xxl-job\doc\db\tables_xxl_job.sql)
3、在xxl-job jdbc连接配置加上&serverTimezone=UTC否则报错(xxl-job\xxl-job-admin\src\main\resources\application.properties)
4、启动项目XxlJobAdminApplication和XxlJobExecutorApplication
在这里插入图片描述

7 运行官方Demo执行器实现定时任务

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值