In the daily development summary, you often encounter scenarios that require timed tasks. Simple, you can use Spring's timed task scheduling framework or Quartz.Either way, there is a problem that needs to be solved, that is, the cluster problem.Typically, a timed task can and can only run on one application instance.
premise
This project is based on spring boot 2.1.7.RELEASE
Project Configuration
1. pom Dependency
As shown in the following figure:
2. yml Configuration
The yml configuration is as follows:
3. quartz.properties
The quartz-related attribute configuration is shown in the following figure:
Be careful:
1. Most importantly, set org.quartz.jobStore.isClustered=true to turn on cluster mode
2. Notes on other configurations
4. Scheduler Configuration
Use Scheduler FactoryBeanCustomizer Personalized Scheduler
@Configuration
public class SysConfig {
private final DataSource dataSource;
public SysConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
public SchedulerFactoryBeanCustomizer schedulerFactoryBeanCustomizer() {
return (schedulerFactoryBean) -> {
schedulerFactoryBean.setDataSource(dataSource);
schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
};
}
}
V. System Startup
System startup, if quartz is shown to start in cluster mode, proves successful.As shown in the diagram:
Writing tasks
I. Job
The code is as follows:
package com.luas.quartz.cluster.demo.quartz.job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class UserJob extends QuartzJobBean {
@Value("${server.port}")
private String port;
private String name;
private Integer age;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println(String.format("the user job is execute on port %s. it's name is %s, age is %s", port, name, age));
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2. Controller Trigger
The code is as follows:
package com.luas.quartz.cluster.demo.controller;
import com.luas.quartz.cluster.demo.quartz.job.UserJob;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/job")
public class JobController {
@Autowired
private Scheduler scheduler;
@RequestMapping("/user")
public Object user() throws Exception {
JobBuilder jobBuilder = JobBuilder
.newJob(UserJob.class)
.withIdentity(new JobKey("UserJob", "default"))
.withDescription("a demo quartz job")
.storeDurably();
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("name", "luas");
jobDataMap.put("age", 18);
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger()
.withIdentity(new TriggerKey("UserJob's trigger 1", "default"))
.withSchedule(createSimpleScheduleBuilder())
.forJob(new JobKey("UserJob", "default"))
.usingJobData(jobDataMap)
.startNow();
this.scheduler.scheduleJob(jobBuilder.build(), triggerBuilder.build());
return LocalDateTime.now();
}
private ScheduleBuilder createSimpleScheduleBuilder() {
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMilliseconds(10000)
.withRepeatCount(100);
return simpleScheduleBuilder;
}
}
3. System Startup
Start 8080, 8082 instances in turn.idea can only start one instance by default and needs to be configured to run in parallel to run two identical instances, as shown in the following figure, check Allow parallel run.
Visit: http://localhost:8080/quartz/job/user, page returns current time.
At this point, console information for 8080 and 8082 is shown as follows:
8080:
8082:
You can see that Quartz runs on 8080 instances and 8082 instances are under monitoring.
4. Switching Running Instances
Stop 8080 instances, manually simulate server failures, observe the console output of 8082 instances, and find that quartz is running on 8082 instances, as shown in the diagram:
8080 stop:
8082 take-over:
problem
1. Startup error: Couldn't store job: JobDataMap values must be Strings when the'useProperties'property is set.
Modify org.quartz.jobStore.useProperties=false in quartz.properties configuration
2. How will the port attribute labeled with the @Value annotation in UserJob be automatically injected, and how will the name and age attributes be automatically injected?
Refer to the following sections of the QuartzAutoConfiguration, SpringBeanJobFactory class:
3. Data structure
Download distribution packages on Quartz's website. Download Address .After downloading, under the compressed package path docs\dbTables, there are script files corresponding to each database, and you can select your own script to execute.For example, tables_mysql_innodb.sql was chosen for this article.
Other
1. Source Code
The source addresses for this article are as follows:
-
github: https://github.com/liuminglei/learning-demo/tree/master/quartz-cluster-demo
-
gitee: https://gitee.com/xbd521/learning-demo/tree/master/quartz-cluster-demo
2. Integration Framework
Quatz-based clustered, non-clustered lightweight encapsulated timed task scheduling framework-quartz, quartz-boot has been shared, configuration, operation is more convenient and efficient, welcome star, fork.
quartz-boot:
-
github: https://github.com/liuminglei/quartz-boot
-
gitee: https://gitee.com/xbd521/quartz-boot
quartz
-
github: https://github.com/liuminglei/quartz
-
gitee: https://gitee.com/xbd521/quartz
This article was originally created by Milky Way Architect. Please indicate the author and source for reprinting.The address of this article is also attached:
https://www.cnblogs.com/luas/p/12040304.html
WeChat Search [Galaxy Architect] found more exciting content.