Second, the quartz cluster of the solution of the timing dispatch in the cluster environment

Source: Internet
Author: User
Tags aop db2 tomcat
problems that may occur in a clustered environment

In the previous blog we introduced how to add the quartz timing scheduling engine from scratch in your project, which is a quartz and spring integration process, it is easy to implement, but we are now in the enterprise project is usually deployed in the cluster environment, In this way we have the timing of scheduling problems, because our scheduled tasks are loaded in memory, each cluster node in the scheduler will be executed, there will be repeated execution and resource competition problems, then how to solve such problems, look down on it ... Solution Solutions

In general enterprises to solve similar problems are generally deployed on a note quartz Other note is not deployed (or in several other machines plus IP address filtering), but so the cluster for the scheduled task is meaningless, and there is a single point of failure of the hidden danger, That is, when the machine that deploys the quartz is hung up, our scheduled tasks stop serving, which is definitely not what we want.

Quartz itself is a support cluster, we solve this problem by quartz cluster way. Quartz cluster


While a single Quartz instance can give you a good job scheduling capability, it does not allow typical enterprise requirements, such as scalability, high reliability, to be met. If you need the ability to fail over and run an ever-increasing number of job,quartz clusters, it's bound to be part of your dialect, and even if one of the machines crashes at the worst of times, it ensures that all jobs are executed.

Quartzjob Scheduling Framework

Understanding the benefits of the quartz cluster, the next step is to transform our previous project to add quartz cluster features.

Quartz a node in a cluster relies on a database to propagate the state of a Scheduler instance, you can only apply Quartz clusters when using JDBC Jobstore

So the first step in our cluster is to build the 12 tables that are needed for quartz 1, to build a table

Build the related table structure in the quartz core package with the built-in statements provided by quartz


The resulting table structure is as follows

These tables are used to store information such as task information, triggers, schedulers, cluster nodes, etc.

Detailed Explanation:
Qrtz_calendars storing quartz calendar information in BLOB type
Qrtz_cron_triggers storage cron Trigger, including cron expressions and time zone information
Qrtz_fired_triggers stores state information related to triggered trigger and execution information for the associated job
Qrtz_paused_trigger_grps storing information for a paused TRIGGER group
Qrtz_scheduler_state stores a small amount of state information about the SCHEDULER, and other SCHEDULER instances (if used in a cluster)
Qrtz_locks the non-locking information of the stored program (if a pessimistic lock is used)
Qrtz_job_details store details for each configured JOB
Qrtz_job_listeners storing information about configured Joblistener
Qrtz_simple_triggers stores simple trigger, including number of repetitions, intervals, and number of touches
Qrtz_blog_triggers Trigger as BLOB type storage (for quartz users to create their own custom Trigger types with JDBC, Jobstore does not know how to store instances)
Qrtz_trigger_listeners storing information for configured Triggerlistener
Qrtz_triggers storing information for configured trigger
All tables default to the previous prefix qrtz_ start.  Modifications can be configured by the Quartz.properties (org.quartz.jobstore.tableprefix= qrtz_). 2. Writing quartz.properties files

set up the quartz.properties file to put it in the SRC directory of the project, as follows:

#============================================================================

# Configure Main Scheduler Properties

#============================================================================

Org.quartz.scheduler.instanceName = Mscheduler

org.quartz.scheduler.instanceId = AUTO

org.quartz.jobstore.clustercheckininterval=20000

#============================================================================

# Configure ThreadPool

#============================================================================

Org.quartz.threadPool.class = Org.quartz.simpl.SimpleThreadPool

Org.quartz.threadPool.threadCount = 3

Org.quartz.threadPool.threadPriority = 5

#============================================================================

# Configure Jobstore

#============================================================================

#org. Quartz.jobStore.class = Org.quartz.simpl.RAMJobStore

Org.quartz.jobStore.class = Org.quartz.impl.jdbcjobstore.JobStoreTX

#org. Quartz.jobStore.driverDelegateClass = Org.quartz.impl.jdbcjobstore.StdJDBCDelegate

Org.quartz.jobStore.useProperties = True

#org. Quartz.jobStore.dataSource = MyDS

Org.quartz.jobStore.tablePrefix = Qrtz_

org.quartz.jobStore.isClustered = True

Org.quartz.jobstore.maxmisfirestohandleatatime=1

#============================================================================

# Configure DataSources

#============================================================================

#mysql

#org. Quartz.dataSource.myDS.driver = Com.ibm.db2.jcc.DB2Driver

#org. Quartz.dataSource.myDS.URL = jdbc:db2://localhost:50000/db

#org. Quartz.dataSource.myDS.user = DB2

#org. Quartz.dataSource.myDS.password = DB2

#org. quartz.dataSource.myDS.maxConnections = 5

#oracle

#org. Quartz.dataSource.myDS.driver = Oracle.jdbc.driver.OracleDriver

#org. Quartz.dataSource.myDS.URL = Jdbc:oracle:thin: @localhost: 1521:ORCL

#org. Quartz.dataSource.myDS.user = Scott

#org. Quartz.dataSource.myDS.password = Shao

#org. quartz.dataSource.myDS.maxConnections = 5

#For Tomcat

Org.quartz.jobStore.driverDelegateClass =org.quartz.impl.jdbcjobstore.oracle.oracledelegate

#For Weblogic & Websphere

#org. Quartz.jobStore.driverDelegateClass = Org.quartz.impl.jdbcjobstore.WebLogicDelegate

Org.quartz.jobStore.useProperties = False

Org.quartz.jobStore.dataSource = MyDS

#JNDI MODE

#For Tomcat

Org.quartz.datasource.myds.jndiurl=java:comp/env/jdbc/oracle

#For Weblogic & Websphere

#org. quartz.datasource.myds.jndiurl=jdbc/oracle

#============================================================================

# Configure Plugins

#============================================================================

#org. Quartz.plugin.triggHistory.class = Org.quartz.plugins.history.LoggingJobHistoryPlugin

#org. Quartz.plugin.jobInitializer.class = Org.quartz.plugins.xml.JobInitializationPlugin

#org. Quartz.plugin.jobInitializer.fileNames = Jobs.xml

#org. Quartz.plugin.jobInitializer.overWriteExistingJobs = True

#org. Quartz.plugin.jobInitializer.failOnFileNotFound = True

#org. Quartz.plugin.jobInitializer.scanInterval = 10

#org. Quartz.plugin.jobInitializer.wrapInUserTransaction = False

The red bold part is the configuration required by the cluster

The core configuration is explained as follows:

The Org.quartz.jobStore.class property is Jobstoretx,
Persist the task to the data. Because nodes in a cluster rely on databases to propagate the state of scheduler instances, you can only apply quartz clusters when using JDBC Jobstore.

The Org.quartz.jobStore.isClustered property is true to notify the scheduler instance that it participates in a cluster.

Org.quartz.jobStore.clusterCheckinInterval

The Scheduler property defines the frequency, in milliseconds, that an instance of a sample is checked into the database.
Scheduler Check if other instances have not been checked in when they should be checked in;
This can indicate a failed scheduler instance, and the current scheduler will take over any job that fails and is recoverable.
With the check-in operation, Scheduler also updates its own status record. The smaller the clusterchedkininterval, the more frequently the scheduler node checks for scheduler instances that fail. The default value is 20000 (that is, 20 seconds)

3. Modify the Spring-time.xml file

<?xmlversion= "1.0" encoding= "UTF-8"?>

<! Doctypebeanspublic "-//spring//dtd bean//en"

"Http://www.springframework.org/dtd/spring-beans.dtd" >

<beans>

<!--scheduler lazy-init= ' false ' then the container starts executing the scheduler--

<beanid= "Startquertz" lazy-init= "false" autowire= "no" class= " Org.springframework.scheduling.quartz.SchedulerFactoryBean ">

<property name= "DataSource" ref= "DataSource"/>

<property name= "configlocation" value= "classpath:quartz.properties"/>

<propertyname= "Triggers" >

<list>

<refbean= "Dotime"/>

</list>

</property>

<!--allows you to use the Spring instance factory in the quartz context--

<propertyname= "Applicationcontextschedulercontextkey" value= "ApplicationContext"/>

</bean>

<!--triggers--

<beanid= "Dotime" class= "Org.springframework.scheduling.quartz.CronTriggerBean" >

<propertyname= "Jobdetail" ref= "Jobtask" ></property>

<!--cron Expressions--

<propertyname= "Cronexpression" value= "10,15,20,25,30,35,40,45,50,55 * * * *?" ></property>

</bean>

<!--tasks--

<beanid= "Jobtask" class= "Org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" >

<propertyname= "TargetObject" ref= "Synusersjob" ></property>

<propertyname= "Targetmethod" value= "Execute" ></property>

</bean>

<!--the work class to invoke--

<beanid= "Synusersjob" class= "Org.leopard.core.quartz.job.SynUsersJob" ></bean>

</beans>

Add red Bold Part code, inject data source and load Quartz.properties file

 

OK Quartz cluster configuration Only these steps, let's start the project ...

We're starting to open up .... Error!

17:00:59,718 ERROR contextloader:215-context initialization failed

Org.springframework.beans.factory.BeanCreationException:Error creating Bean with Name ' Startquertz ' defined in Class path resource [Config/spring/spring-time.xml]: Invocation of Init method failed; Nested exception is org.quartz.JobPersistenceException:Couldn ' t store job:unable to serialize Jobdatamap for insertion in To database because the value of "MethodInvoker" is not Serializable:org.springframework.scheduling.quartz.Meth Odinvokingjobdetailfactorybean [see nested exception:java.io.NotSerializableException:Unable to serialize Jobdatamap For insertion to database because the value of property ' MethodInvoker ' was not Serializable:org.springframework.schedul Ing.quartz.MethodInvokingJobDetailFactoryBean]

 

We mainly look at the red part, the main reason is that the MethodInvoking method in the Methodinvokingjobdetailfactorybean class is not serializable, so in the quartz task This serializable error is thrown when serializing into the database

4, solve serializable error solution

Check the Internet, to solve this problem, there are two main options: 4.1. Change the source code of Spring

Blog Address: http://jira.springframework.org/browse/SPR-3797

The author rewrote the Methodinvokingjobdetailfactorybean

4.2. Facet refactoring of Spring source through AOP reflection

Blog Address: http://blog.csdn.net/lifetragedy/article/details/6212831

Rewrite your own class according to Quartzjobbean, and then use SPRING to inject the overridden class (we name it: Mydetailquartzjobbean) into AppContext, and then use AOP technology to reflect the original Quartzjo BX (The execution class that the developer has already done to perform the QUARTZ job).

two ways I have been tested, can solve the problem, we here first solve this bug in the second way, did not modify any spring source 4.2.1, increase Mydetailquartzjobbean.java

Package Org.leopard.core.quartz;

Import Java.lang.reflect.Method;

Import Org.apache.commons.logging.Log;

Import Org.apache.commons.logging.LogFactory;

Import Org.quartz.JobExecutionContext;

Import org.quartz.JobExecutionException;

Import Org.springframework.context.ApplicationContext;

Import Org.springframework.scheduling.quartz.QuartzJobBean;

/**

* Solve spring and quartz integration bug

*

*/

public class Mydetailquartzjobbean extends Quartzjobbean {

Protected final Log logger = Logfactory.getlog (GetClass ());

Private String TargetObject;

Private String Targetmethod;

Private ApplicationContext CTX;

protected void Executeinternal (Jobexecutioncontext context) throws Jobexecutionexception {

try {

Logger.info ("execute [" + TargetObject + "] at once>>>>>>");

Object otargetobject = Ctx.getbean (TargetObject);

Method m = null;

try {

m = Otargetobject.getclass (). GetMethod (Targetmethod, new class[] {});

M.invoke (Otargetobject, new object[] {});

} catch (SecurityException e) {

Logger.error (e);

} catch (Nosuchmethodexception e) {

Logger.error (e);

}

} catch (Exception e) {

throw new Jobexecutionexception (e);

}

}

public void Setapplicationcontext (ApplicationContext applicationcontext) {

This.ctx = ApplicationContext;

}

public void Settargetobject (String targetObject) {

This.targetobject = TargetObject;

}

public void Settargetmethod (String targetmethod) {

This.targetmethod = Targetmethod;

}

}

5, re-modify the Spring-time.xml file to solve the serializable problem

The contents of the modified Spring-time.xml file are as follows:

<?xmlversion= "1.0" encoding= "UTF-8"?>

<! Doctypebeanspublic "-//spring//dtd bean//en"

        "/http/ Www.springframework.org/dtd/spring-beans.dtd ">

<beans>

 

    <!--scheduler lazy-init= ' false ' then the container starts executing the scheduler--

    <beanid= "Startquertz" lazy-init= " False "Autowire=" no "class=" Org.springframework.scheduling.quartz.SchedulerFactoryBean ">

         <propertyname= "DataSource" ref= "DataSource"/>

         <propertyname= "configlocation" value= "classpath:quartz.properties"/>

         <propertyname=

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.