Mule – Quartz active/passive configuration

Mule can work in multiple instances as single unit in the same flow. This allow a large scalable system and avoid the single point of failure of the system.

In one word we are speaking about the cluster. In this article I’d like to show you how configure a active-passive cluster with quartz connector.

Mule already provides a cluster system named Mule High Availability (HA). This is available in the enterprise edition and it works very well.

You can find out more at http://www.mulesoft.org/documentation/display/MULE3USER/Mule+High+Availability.

But, if for many different reasons you can’t use that version, could I use anyway a cluster system? The answer is, obviously, yes (we are developer!). The home-made solution is based to Jms Message Broker, Jdbc or Quartz.

Now we take a look about this last chance, not in concurrent mode, but in active-passive mode. You have to notice that nothing you’ll see about quartz solution is documentated anywhere; all this comes from my personal experience and it can change in future version. I did it with mule version 2.2.1.

For this purpose I did a very easy mule flow like this:


<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesource.org/schema/mule/core/2.2"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:spring="http://www.springframework.org/schema/beans"
	xmlns:stdio="http://www.mulesource.org/schema/mule/stdio/2.2" xmlns:vm="http://www.mulesource.org/schema/mule/vm/2.2"
	xmlns:jdbc="http://www.mulesource.org/schema/mule/jdbc/2.2"
	xmlns:quartz="http://www.mulesource.org/schema/mule/quartz/2.2"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mulexml="http://www.mulesource.org/schema/mule/xml/2.2"
	xmlns:servlet="http://www.mulesource.org/schema/mule/servlet/2.2"
	xmlns:management="http://www.mulesource.org/schema/mule/management/2.2"

	xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.mulesource.org/schema/mule/core/2.2 http://www.mulesource.org/schema/mule/core/2.2/mule.xsd
       http://www.mulesource.org/schema/mule/stdio/2.2 http://www.mulesource.org/schema/mule/stdio/2.2/mule-stdio.xsd
       http://www.mulesource.org/schema/mule/vm/2.2 http://www.mulesource.org/schema/mule/vm/2.2/mule-vm.xsd
       http://www.mulesource.org/schema/mule/jdbc/2.2 http://www.mulesource.org/schema/mule/jdbc/2.2/mule-jdbc.xsd
       http://www.mulesource.org/schema/mule/quartz/2.2 http://www.mulesource.org/schema/mule/quartz/2.2/mule-quartz.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
       http://www.mulesource.org/schema/mule/xml/2.2 http://www.mulesource.org/schema/mule/xml/2.2/mule-xml.xsd
       http://www.mulesource.org/schema/mule/servlet/2.2 http://www.mulesource.org/schema/mule/servlet/2.2/mule-servlet.xsd
       http://www.mulesource.org/schema/mule/management/2.2 http://www.mulesource.org/schema/mule/management/2.2/mule-management.xsd">

	<quartz:connector name="quartzConnectorCluster">
		<quartz:factory-property
			key="org.quartz.scheduler.makeSchedulerThreadDaemon" value="true" />
		<quartz:factory-property key="org.quartz.jobStore.makeThreadsDaemons"
			value="true" />
		<quartz:factory-property key="org.quartz.scheduler.instanceName"
			value="MyClusteredSchedulerRec" />
		<quartz:factory-property key="org.quartz.scheduler.instanceId"
			value="AUTO" />
		<quartz:factory-property key="org.quartz.threadPool.class"
			value="org.quartz.simpl.SimpleThreadPool" />
		<quartz:factory-property key="org.quartz.threadPool.threadCount"
			value="15" />
		<quartz:factory-property key="org.quartz.threadPool.threadPriority"
			value="5" />
		<quartz:factory-property key="org.quartz.jobStore.misfireThreshold"
			value="60000" />
		<quartz:factory-property key="org.quartz.jobStore.class"
			value="org.quartz.impl.jdbcjobstore.JobStoreTX" />
		<quartz:factory-property key="org.quartz.jobStore.driverDelegateClass"
			value="org.quartz.impl.jdbcjobstore.StdJDBCDelegate" />
		<quartz:factory-property key="org.quartz.jobStore.useProperties"
			value="false" />
		<quartz:factory-property key="org.quartz.jobStore.dataSource"
			value="myDSRec" />
		<quartz:factory-property key="org.quartz.jobStore.tablePrefix"
			value="CLU_" />
		<quartz:factory-property key="org.quartz.jobStore.isClustered"
			value="true" />
		<quartz:factory-property key="org.quartz.jobStore.clusterCheckinInterval"
			value="20000" />
		<quartz:factory-property key="org.quartz.dataSource.myDSRec.driver"
			value="org.gjt.mm.mysql.Driver" />
		<quartz:factory-property key="org.quartz.dataSource.myDSRec.URL"
			value="jdbc:mysql://cluster:3306/Quartz" />
		<quartz:factory-property key="org.quartz.dataSource.myDSRec.user"
			value="quartz" />
		<quartz:factory-property key="org.quartz.dataSource.myDSRec.password"
			value="quartz" />
		<quartz:factory-property
			key="org.quartz.dataSource.myDSRec.maxConnections" value="5" />
		<quartz:factory-property
			key="org.quartz.dataSource.myDSRec.validationQuery" value="select 0 from dual" />
	</quartz:connector>

	<quartz:connector name="quartzConnectorClusterBackup">
		<quartz:factory-property
			key="org.quartz.scheduler.makeSchedulerThreadDaemon" value="true" />
		<quartz:factory-property key="org.quartz.jobStore.makeThreadsDaemons"
			value="true" />
		<quartz:factory-property key="org.quartz.scheduler.instanceName"
			value="MyClusteredSchedulerBackup" />
		<quartz:factory-property key="org.quartz.scheduler.instanceId"
			value="AUTO" />
		<quartz:factory-property key="org.quartz.threadPool.class"
			value="org.quartz.simpl.SimpleThreadPool" />
		<quartz:factory-property key="org.quartz.threadPool.threadCount"
			value="15" />
		<quartz:factory-property key="org.quartz.threadPool.threadPriority"
			value="5" />
		<quartz:factory-property key="org.quartz.jobStore.misfireThreshold"
			value="60000" />
		<quartz:factory-property key="org.quartz.jobStore.class"
			value="org.quartz.impl.jdbcjobstore.JobStoreTX" />
		<quartz:factory-property key="org.quartz.jobStore.driverDelegateClass"
			value="org.quartz.impl.jdbcjobstore.StdJDBCDelegate" />
		<quartz:factory-property key="org.quartz.jobStore.useProperties"
			value="false" />
		<quartz:factory-property key="org.quartz.jobStore.dataSource"
			value="myDSRec" />
		<quartz:factory-property key="org.quartz.jobStore.tablePrefix"
			value="CLUBACKUP_" />
		<quartz:factory-property key="org.quartz.jobStore.isClustered"
			value="true" />
		<quartz:factory-property key="org.quartz.jobStore.clusterCheckinInterval"
			value="20000" />
		<quartz:factory-property key="org.quartz.dataSource.myDSRec.driver"
			value="org.gjt.mm.mysql.Driver" />
		<quartz:factory-property key="org.quartz.dataSource.myDSRec.URL"
			value="jdbc:mysql://cluster:3306/Quartz" />
		<quartz:factory-property key="org.quartz.dataSource.myDSRec.user"
			value="quartz" />
		<quartz:factory-property key="org.quartz.dataSource.myDSRec.password"
			value="quartz" />
		<quartz:factory-property
			key="org.quartz.dataSource.myDSRec.maxConnections" value="5" />
		<quartz:factory-property
			key="org.quartz.dataSource.myDSRec.validationQuery" value="select 0 from dual" />
	</quartz:connector>

	<model name="clusterQuartz">
		<!--
			A Mule service defines all the necessary information about how your
			components will interact with the framework, other components in the
			system and external sources. Please refer to the Configuration Guide
			for a full description of all the parameters.
		-->
		<service name="publish">
			<inbound>
				<quartz:inbound-endpoint cronExpression="2/10 * * * * ?"
					connector-ref="quartzConnectorCluster" jobName="clusterQuartz.Start1">
					<property key="payload" value="FLOW 1" />
					<quartz:event-generator-job />
				</quartz:inbound-endpoint>
				<quartz:inbound-endpoint cronExpression="6/10 * * * * ?"
					connector-ref="quartzConnectorClusterBackup" jobName="clusterQuartz.Start2">
					<property key="payload" value="FLOW 2" />
					<quartz:event-generator-job />
				</quartz:inbound-endpoint>
			</inbound>
			<outbound>
				<pass-through-router>
					<stdio:outbound-endpoint system="OUT"
						responseTimeout="10" />
				</pass-through-router>
			</outbound>
		</service>
	</model>
</mule>

In that mule flow we have two quartz connectors which send a payload every 10 seconds. Our purpose is to force the quartz trigger always in the same machine.

Let me show you the idea with this diagram:

At my database I’ve got two quartz tables set. A table set for “CLU_” (Master) and table set for “CLUBACKUP_” (Backup)

Now it’s time to running the service!

First we run the service of master instance. We’ll see an output like this:


**********************************************************************
* Mule ESB and Integration Platform                                  *
* Version: 2.2.1 Build: 14422                                        *
* MuleSource, Inc.                                                   *
* For more information go to http://mule.mulesource.org              *
*                                                                    *
* Server started: 6/28/12 9:49 AM                                    *
* Server ID: c888e21f-c0f5-11e1-aa33-196200839606                    *
* JDK: 1.6.0_06 (mixed mode)                                         *
* OS encoding: UTF-8, Mule encoding: UTF-8                           *
* OS: Linux (2.6.18-194.el5xen, i386)                                *
* Host: Master (192.168.60.36)                                       *
*                                                                    *
* Agents Running: None                                               *
**********************************************************************
INFO  2012-06-28 09:49:32,029 [MyClusteredSchedulerRec_QuartzSchedulerThread] org.mule.DefaultMuleContext: readObject
INFO  2012-06-28 09:49:32,046 [connector.stdio.0.dispatcher.3] org.mule.transport.stdio.StdioMessageDispatcher: Connected: endpoint.outbound.stdio://system.out
FLOW 1
INFO  2012-06-28 09:49:36,029 [MyClusteredSchedulerBackup_QuartzSchedulerThread] org.mule.DefaultMuleContext: readObject
INFO  2012-06-28 09:49:36,244 [connector.stdio.0.dispatcher.4] org.mule.transport.stdio.StdioMessageDispatcher: Connected: endpoint.outbound.stdio://system.out
FLOW 2

First we run the service of backup instance. We’ll see an output like this:


**********************************************************************
* Mule ESB and Integration Platform                                  *
* Version: 2.2.1 Build: 14422                                        *
* MuleSource, Inc.                                                   *
* For more information go to http://mule.mulesource.org              *
*                                                                    *
* Server started: 6/28/12 9:50 AM                                    *
* Server ID: c888e21f-c0f5-11e1-aa33-547895478943                    *
* JDK: 1.6.0_06 (mixed mode)                                         *
* OS encoding: UTF-8, Mule encoding: UTF-8                           *
* OS: Linux (2.6.18-194.el5xen, i386)                                *
* Host: Backup (192.168.60.37)                                       *
*                                                                    *
* Agents Running: None                                               *
**********************************************************************

You’ll never see anything in backup output because, everything, is running in master server. The next step is to stop the master server. Once the master server is down, you can see the flows in execution in backup server.

Unfortunately, you can’t decide which is the master server and the backup server. Easily, the first that run the flows gets the master role, the others are the backup.

This solution works only whether every database suffix contains only one quartz flow.

Again, this is a home made solution. The best solution is still the Mule High Availability. I wanted to share with you this trick, it can be useful in decision if you can’t buy enterprise Mule edition and it’s Mule HA. Keep in mind  that you can use other solution for building Cluster in mule (Jms broker is another solution).

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s