Quartz Sample Code Spring integrate distributed scheduling

Foreword

In order to ensure high availability and high concurrency applications, usually deploy multiple nodes; for regular tasks, if each node to perform their regular tasks, while consuming system resources,

On the other hand some tasks multiple times, may lead to application logic issues, so they need a distributed scheduling system to coordinate each node to perform regular tasks.

Spring Quartz integration

Quartz is a sophisticated task scheduling system, Spring of Quartz made compatible for easy development, the following specific look at how to integrate:

1.Maven dependent files

<dependencies>
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>4.3.5.RELEASE</version>
 </dependency>
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>4.3.5.RELEASE</version>
 </dependency>
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-tx</artifactId>
  <version>4.3.5.RELEASE</version>
 </dependency>
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>4.3.5.RELEASE</version>
 </dependency>
 <dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz</artifactId>
  <version>2.2.3</version>
 </dependency>
 <dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.29</version>
 </dependency>
 </dependencies>

Mainly Spring related libraries, quartz and mysql database driver library, NOTE: distributed scheduling needs a database, where the choice of mysql;

2. Configure job

It provides two ways to configure job, namely: MethodInvokingJobDetailFactoryBean and JobDetailFactoryBean

2.1MethodInvokingJobDetailFactoryBean

To call a specific a method used when the bean, the specific configuration is as follows:

<bean id="firstTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> 
  <property name="targetObject" ref="firstService" /> 
  <property name="targetMethod" value="service" /> 
</bea>

2.2JobDetailFactoryBean

This approach is more flexible and can pass parameters set as follows:

<bean id="firstTask"
 class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
 <property name="jobClass" value="zh.maven.SQuartz.task.FirstTask" />
 <property name="jobDataMap">
  <map>
  <entry key="firstService" value-ref="firstService" />
  </map>
 </property>
</bean>

 

jobClass defined task classes, inheritance QuartzJobBean, implement a method executeInternal; JobDataMap used to transfer data to the job

3. triggers used to configure the scheduler

Also it offers two types of triggers: SimpleTriggerFactoryBean and CronTriggerFactoryBean

Look at the focus CronTriggerFactoryBean, this type is more flexible, as follows:

<bean id="firstCronTrigger"
 class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
 <property name="jobDetail" ref="firstTask" />
 <property name="cronExpression" value="0/5 * * ? * *" />
 </bean>

jobDetail configuration is specified in step 2 job, cronExpression arranged Job performed once every 5 seconds;

4. Quartz scheduler configured SchedulerFactoryBean

Also provides two ways: memory RAMJobStore and database mode

4.1 Memory RAMJobStore

job-related information is stored in memory, each node stores a respective, mutually isolated, configured as follows:

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
 <property name="triggers">
  <list>
  <ref bean="firstCronTrigger" />
  </list>
 </property>
 </bean>

4.2 database mode

The job information stored in the database, a common database for all the nodes, each node communicate via a database, at the same time to ensure that a job will be executed on one node, and

If a node hang, Job will be assigned to the other node to perform the specific configuration is as follows:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
 destroy-method="close">
 <property name="driverClass" value="com.mysql.jdbc.Driver" />
 <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/quartz" />
 <property name="user" value="root" />
 <property name="password" value="root" />
 </bean>
 <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
 <property name="dataSource" ref="dataSource" />
 <property name="configLocation" value="classpath:quartz.properties" />
 <property name="triggers">
  <list>
  <ref bean="firstCronTrigger" />
  </list>
 </property>
 </bean>

dataSource source for configuration data, information related to data tables, may be downloaded to the official website gz package, sql file path: \ at dbTables docs, which provides a mainstream sql file database;

configLocation quartz.properties file configured under the quartz.jar org.quartz package, which provides some default data, such as org.quartz.jobStore.class

org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

It should be quartz.properties copy out to make some changes, specific changes are as follows:

org.quartz.scheduler.instanceId: AUTO
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.isClustered: true
org.quartz.jobStore.clusterCheckinInterval: 1000

5. Class

public class FirstTask extends QuartzJobBean {
 
 private FirstService firstService;
 
 @Override
 protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
 firstService.service();
 }
 
 public void setFirstService(FirstService firstService) {
 this.firstService = firstService;
 }
}

FirstTask inheritance QuartzJobBean, achieve executeInternal method, call FirstService

public class FirstService implements Serializable {
 
 private static final long serialVersionUID = 1L;
 
 public void service() {
 System.out.println(new SimpleDateFormat("YYYYMMdd HH:mm:ss").format(new Date()) + "---start FirstService");
 try {
  Thread.sleep(2000);
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 System.out.println(new SimpleDateFormat("YYYYMMdd HH:mm:ss").format(new Date()) + "---end FirstService");
 }
}

FirstService desirable to provide serial interfaces, because of the need to save in a database;

public class App {
 public static void main(String[] args) {
 AbstractApplicationContext context = new ClassPathXmlApplicationContext("quartz.xml");
 }
}

Class is used to load the main quartz profile;

Testing distributed scheduling

1. Start App while twice observed logs:

20180405 14:48:10---start FirstService
20180405 14:48:12---end FirstService
20180405 14:48:15---start FirstService
20180405 14:48:17---end FirstService

Wherein A1, log output, A2 no; When stopped A1, A2 have a log output;

2. Add a new job are new: SecondTask and SecondService, while adding the relevant configuration file, start the App twice observed logs:

A1日志如下:

20180405 15:03:15---start FirstService
20180405 15:03:15---start SecondService
20180405 15:03:17---end FirstService
20180405 15:03:17---end SecondService
20180405 15:03:20---start FirstService
20180405 15:03:22---end FirstService
20180405 15:03:25---start FirstService
20180405 15:03:27---end FirstService

A2日志如下:

20180405 15:03:20---start SecondService
20180405 15:03:22---end SecondService
20180405 15:03:25---start SecondService
20180405 15:03:27---end SecondService

Can be found in A1 and A2 have a mission, but only in the same task at the same time a node to perform, and there may only be assigned to other nodes after the end of execution;

3. If the time interval is less than the execution time of the task, such as here into sleep (6000)

A1日志如下:

20180405 15:14:40---start FirstService
20180405 15:14:45---start FirstService
20180405 15:14:46---end FirstService
20180405 15:14:50---start FirstService
20180405 15:14:50---start SecondService
20180405 15:14:51---end FirstService

A2日志如下:

20180405 15:14:40---start SecondService
20180405 15:14:45---start SecondService
20180405 15:14:46---end SecondService
20180405 15:14:51---end SecondService

Interval time is 5 seconds, 6 seconds and task execution, observation logs can be found, the task is not over, has started a new job, this may lead to the application of logical problems, in fact, the task can not support serial issues;

4. @ DisallowConcurrentExecution annotation task to ensure the serial

In the Add FirstTask and SecondTask respectively @DisallowConcurrentExecution annotation log results are as follows:

A1日志如下:

20180405 15:32:45---start FirstService
20180405 15:32:51---end FirstService
20180405 15:32:51---start FirstService
20180405 15:32:51---start SecondService
20180405 15:32:57---end FirstService
20180405 15:32:57---end SecondService
20180405 15:32:57---start FirstService
20180405 15:32:57---start SecondService

A2日志如下:

20180405 15:32:45---start SecondService
20180405 15:32:51---end SecondService

Observe the log can be found only in the task after the end, we will start a new task, to achieve a serialization tasks;

to sum up

This paper aims Spring + Quartz distributed scheduling have an intuitive understanding, to solve the problem by actual use, of course, there may be a lot of questions such as how it is scheduling, database and so what would happen if hung up, needs to be done more in-depth understanding.

https://mp.weixin.qq.com/s/vkvYJnKfQyuUeD_BDQy_1g

For more learning materials, can be added to the group: 473 984 645 or under the Fanger Wei code scanning

 

Guess you like

Origin www.cnblogs.com/lemonrel/p/11767096.html
Recommended