Quartz定时任务框架(二)- 集群

1. Quartz搭建集群

1.1 背景

  • 集群只有一台服务器调用定时任务,浪费了其他机器性能
  • 集群中的每台服务器调用定时任务,但是一个任务只会分配到一个集群中的一台服务器上

1.2 搭建Quartz集群

Quartz定时任务框架(二)- 集群_第1张图片

1.2.1 配置application.yml文件

Quartz定时任务框架(二)- 集群_第2张图片

配置主配置文件application.yml

spring:
  profiles:
    # 告知spring读取自定义配置文件
    include: 1,2
  datasource:
    url: jdbc:mysql://127.0.0.1/quartzTest?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
  quartz:
    job-store-type: JDBC
    jdbc:
      initialize-schema: always

配置Quartz集群文件

  • application1.yml
spring:
  quartz:
    properties:
      # 设置Quartz集群名称
      org.quartz.scheduler.instanceName: OrderService
      # 设置Quartz集群标识ID
      org.quartz.scheduler.instanceId: Order_1
      # 是否设为集群模式
      org.quartz.jobStore.isClustered: true
      # 设置线程数
      org.quartz.threadPool.threadCount: 3

  • application2.yml
spring:
  quartz:
    properties:
      # 设置Quartz集群名称
      org.quartz.scheduler.instanceName: OrderService
      # 设置Quartz集群标识ID
      org.quartz.scheduler.instanceId: Order_2
      # 是否设为集群模式
      org.quartz.jobStore.isClustered: true
      # 设置线程数
      org.quartz.threadPool.threadCount: 3

1.2.2 配置Project Structure

  • ShareQuartzApplication1
    Quartz定时任务框架(二)- 集群_第3张图片
  • ShareQuartzApplication2
    Quartz定时任务框架(二)- 集群_第4张图片

1.2.3 编辑JobClusterInit类

实现多个任务依次调用

package com.mochasoft.jobconfig;

import com.mochasoft.job.SpringBootJob1;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;

@Component
public class JobClusterInit {

    // springboot自动注入Scheduler调度器
    @Autowired
    private Scheduler scheduler;

    /**
     * @PostConstruct
     * 修饰非静态void()方法。该方法会在服务器家在Servlet时候运行,并且只会被服务器执行一次。
     * 该方法在构造函数之后执行,init()方法之前执行。
     * 该注解的方法在整个Bean初始化中的执行顺序:
     * Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
     * */
    @PostConstruct
    public void initJob() throws SchedulerException {
        startJob1("job-1", "trigger-1");

        startJob1("job-2", "trigger-2");

        startJob1("job-3", "trigger-3");
    }

    private void startJob1(String jobName, String triggerName) throws SchedulerException {
        // 创建JobDetail
        JobDetail jobDetail  = JobBuilder.newJob(SpringBootJob1.class)
                .withIdentity(jobName)
                .build();

        // 创建Trigger
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(triggerName)
                .startNow() // 立即开始
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(10)) // 每隔10s执行一次,一直执行下去
                .build();
        // 调度器执行
        scheduler.scheduleJob(jobDetail, trigger);
    }
}

1.2.4 配置主启动类

package com.mochasoft;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.PostConstruct;
import java.util.StringJoiner;

@SpringBootApplication
public class ShareQuartzApplication {

	@Autowired
	private Scheduler scheduler;

	@Value("${spring.quartz.properties.org.quartz.scheduler.instanceId}")
	private String sInstanceId;

	// 打印当前执行Quartz集群ID
	@PostConstruct
	public void getInstanceId() {
		String instanceName = "";
		String instanceId = "";
		try {
			instanceName = scheduler.getMetaData().getSchedulerName();
			instanceId = scheduler.getMetaData().getSchedulerInstanceId();
		} catch (SchedulerException e) {
			e.printStackTrace();
		}

		System.out.println(
				new StringJoiner("|")
				.add(sInstanceId) // spring获取到的instanceId
				.add(instanceName) // Quartz获取的instanceName
				.add(instanceId) // Quartz获取的instanceId
		);
	}

	public static void main(String[] args) {
		SpringApplication.run(ShareQuartzApplication.class, args);
	}

}

1.2.5 启动两个启动类,查看控制台输出

  • ShareQuartzApplication1
    Quartz定时任务框架(二)- 集群_第5张图片
  • ShareQuartzApplication2
    Quartz定时任务框架(二)- 集群_第6张图片
    分析结果
  • 没有真正实现集群模式功能实现
  • 时间出现混乱(每次启动都会从新删除数据库表,导致时间计时出错)

1.3 实现Quartz集群

1.3.1 启动ShareQuartzApplication1

启动完成后

  • 修改application.yml配置文件中自动重建quartz表的配置,此时表中已经有了定时任务

Quartz定时任务框架(二)- 集群_第7张图片

  • 因为数据库表中已经有任务,则注掉@Component注解
    Quartz定时任务框架(二)- 集群_第8张图片

1.3.2 重启两个启动类,查看控制台输出

Quartz定时任务框架(二)- 集群_第9张图片
Quartz定时任务框架(二)- 集群_第10张图片
查看两个输出结果发现,实现了集群效果,但是读取的配置文件出现了问题-无法正常读取到指定的ymk配置:
解决方案:在spring前面添加“–”,使指定配置路径生效
Quartz定时任务框架(二)- 集群_第11张图片

1.4 实现Quartz分区

1.4.1 背景

当定时任务过多时,会导致性能下降,为了提升性能,在硬件与软件版本固定的情况下,可以通过分区的形式来提升性能

1.4.2 编辑yml配置

application-dev.ymlQuartz定时任务框架(二)- 集群_第12张图片

Quartz定时任务框架(二)- 集群_第13张图片

1.4.3 编辑JobClusterPartitionInit类

Quartz定时任务框架(二)- 集群_第14张图片

package com.mochasoft.jobconfig;

import com.mochasoft.job.SpringBootJob1;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;




/**
 * 分析:
 *  该实例化方法实际只执行了一次,可以将初始化的方法实现封装,通过开始调用生成即可
 *
 *
 * */
@Component
public class JobClusterPartitionInit {

    @Value("${spring.quartz.properties.org.quartz.scheduler.instanceName}")
    private String instanceName;

    // springboot自动注入Scheduler调度器
    @Autowired
    private Scheduler scheduler;

    /**
     * @PostConstruct
     * 修饰非静态void()方法。该方法会在服务器家在Servlet时候运行,并且只会被服务器执行一次。
     * 该方法在构造函数之后执行,init()方法之前执行。
     * 该注解的方法在整个Bean初始化中的执行顺序:
     * Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
     * */
    @PostConstruct
    public void initJob() throws SchedulerException {
        startJob1("job-1", "trigger-1","OrderService-dev");

        startJob1("job-2", "trigger-2","OrderService-test");

        startJob1("job-3", "trigger-3","OrderService-dev");
    }

    private void startJob1(String jobName, String triggerName,String partition) throws SchedulerException {
        // 如果集群名称与传入的名称不一致,则直接跳过
        if (!instanceName.equals(partition)) {
            return;
        }
        // 创建JobDetail
        JobDetail jobDetail  = JobBuilder.newJob(SpringBootJob1.class)
                .usingJobData("instanceName", partition)
                .withIdentity(jobName)
                .build();

        // 创建Trigger
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(triggerName)
                .startNow() // 立即开始
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)) // 每隔10s执行一次,一直执行下去
                .build();
        // 调度器执行
        scheduler.scheduleJob(jobDetail, trigger);
    }
}

你可能感兴趣的:(Quartz,quartz,spring,boot)