« Back to Customization

High Availability Guide

This article needs updating. For more information, see Wiki - Need Updating

Introduction #

This article describes how to use Liferay with virtual hosting, load balancing and clustering to ensure high availability for critical-uptime systems.

The Big Picture #

Virtual Hosting #

Example: we will install 3 virtual hosts called: localhost for www.mytcl.com, localhost2 for www.mytte.com, and localhost3 for www.mypmu.com

server.xml #

Add below statement to a host entry localhost2 of the $TOMCAT_HOME/conf/server.xml file:

 <Host name="localhost2" debug="0" appBase="webapp2"
 unpackWARs="true" autoDeploy="true"
 xmlValidation="false" xmlNamespaceAware="false">
 	<Alias>www.mytte.com</Alias>
 	<Alias>mytte.com</Alias>
 </Host>

Repeat the above steps to add a host entry localhost3 of the $TOMCAT_HOME/conf/server.xml file:

 <Host name="localhost3" debug="0" appBase="webapp3"
 unpackWARs="true" autoDeploy="true"
 xmlValidation="false" xmlNamespaceAware="false">
 	<Alias>www.mypmu.com</Alias>
 	<Alias>mypmu.com</Alias>
 </Host>

ROOT.xml #

Add a configuration file for the localhost2 (www.mytte.com)

Step 1: mkdir $TOMCAT_HOME/conf/Catalina/localhost2

Step 2: copy $TOMCAT_HOME/conf/Catalina/localhost/ROOT.xml to $TOMCAT_HOME/conf/Catalina/localhost2/ROOT.xml

Step 3: modify "Context path" of $TOMCAT_HOME/conf/Catalina/localhost2/ROOT.xml

as below:

 < Context path="" debug="0" reloadable="true"
 cookies="true" crossContext="false" privileged="false" >

Repeat above steps to add a configuration file for the localhost3 (www.mypmu.com)

Step 1: mkdir $TOMCAT_HOME/conf/Catalina/localhost3

Step 2: copy $TOMCAT_HOME/conf/Catalina/localhost/ROOT.xml to $TOMCAT_HOME/conf/Catalina/localhost3/ROOT.xml

Step 3: modify "Context path" of $TOMCAT_HOME/conf/Catalina/localhost3/ROOT.xml

as below:

 < Context path="" debug="0" reloadable="true"
 cookies="true" crossContext="false" privileged="false" >

A new host #

Add a new host of localhost2 (www.mytte.com)

Step 1: Create a new folder $TOMCAT_HOME/webapp2/ROOT

Step 2: Copy all the content of $TOMCAT_HOME/webapp/ROOT to $TOMCAT_HOME/webapp2/ROOT

Step 3: Edit $TOMCAT_HOME/webapp2/ROOT/WEB-INF/web.xml modify the company_id to mytte.com

Step 4: Create a new folder $TOMCAT_HOME/webapp2/tunnel

Step 5: Copy all the content of $TOMCAT_HOME/webapps/tunnel to /webapp2/tunnel

Repeat above steps to add a new host of localhost3 (www.mypmu.com)

Step 1: Create a new folder $TOMCAT_HOME/webapp3/ROOT

Step 2: Copy all the content of $TOMCAT_HOME/webapps/ROOT to $TOMCAT_HOME/webapp3/ROOT

Step 3: Edit $TOMCAT_HOME/webapp3/ROOT/WEB-INF/web.xml modify the company_id to mypmu.com

Step 4: Create a new folder $TOMCAT_HOME/webapp3/tunnel

Step 5: Copy all the content of $TOMCAT_HOME/webapp/tunnel to /webapp3/tunnel

hosts configuration in OS environment #

Step 1: hosts

In Windows, modify c:/windows/system32/drivers/etc/hosts as below:

 127.0.0.1 localhost www.mytcl.com
 127.0.0.1 localhost2 www.mytte.com
 127.0.0.1 localhost3 www.mypmu.com

In Linux, modify /etc/hosts as below:

 127.0.0.1 localhost.localdomain localhost
 127.0.0.1 localhost.localdomain localhost2
 127.0.0.1 localhost.localdomain localhost3

Step 2: In Linux, check /etc/host.conf like below:

 order hosts,bind

Step 3: In Linux, check /etc/nsswitch.conf like below:

 hosts: files nisplus nis dns

Shared resources #

Shared resources at $TOMCAT_HOME/common/lib/ext

Step 1: Move all files of $TOMCAT_HOME/liferay/WEB-INF/lib except util-taglib.jar to $TOMCAT_HOME/common/lib/ext

Step 2: And delete duplicated files of $TOMCAT_HOME/webapp2/ROOT/WEB-INF/lib except util-taglib.jar

Repeat step 2 to delete duplicated files of $TOMCAT/webapp3/ROOT/WEB-INF/lib/except util-taglib.jar

Virtual hosting is done #

Step 1: In Linux, change directory to $TOMCAT_HOME/tomcat/bin and run startup.sh

Step 2: browse the results at the same machine: http://localhost:8080, http://localhost2:8080 and http://localhost3:8080

Step 3: If domains are forward to the ip address of the machine, users may browse http://www.mytcl.com:8080, http://www.mytte.com:8080 and http://www.mypmu.com:8080

Tomcat Clustering #

server.xml #

Uncommend the cluster element in $TOMCAT_HOME/conf/server.xml:

         <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
                  managerClassName="org.apache.catalina.cluster.session.DeltaManager"
                  expireSessionsOnShutdown="false"
                  useDirtyFlag="true"
                  notifyListenersOnReplication="true">
             <Membership 
                 className="org.apache.catalina.cluster.mcast.McastService"
                 mcastAddr="228.0.0.4"
                 mcastPort="45564"
                 mcastFrequency="500"
                 mcastDropTime="3000"/>
             <Receiver 
                 className="org.apache.catalina.cluster.tcp.ReplicationListener"
                 tcpListenAddress="auto"
                 tcpListenPort="4001"
                 tcpSelectorTimeout="100"
                 tcpThreadCount="6"/>
             <Sender
                 className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
                 replicationMode="pooled"
                 ackTimeout="15000"
                 waitForAck="true"/>
             <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
                    filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
             <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
                       tempDir="/tmp/war-temp/"
                       deployDir="/tmp/war-deploy/"
                       watchDir="/tmp/war-listen/"
                       watchEnabled="false"/>
             <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
         </Cluster>

<distributable/> #

Make user your web.xml has the <distributable/> element or set at your <Content distributable=”true” />

Step 1: For localhost of www.mytcl.com:

Add <distributable/> between <web-app> into $TOMCAT_HOME/webapps/ROOT/WEB-INF/web.xml:

 <web-app>
 	<distributable/>
 	<context-param>
 	<param-name>company_id</param-name>
 	<param-value>liferay.com</param-value>
 	</context-param>
 . . .
 </web-app>

Step 2: Repeat step 2.2.1 to localhost2 of www.mytte.com, add <distributable/> into $TOMCAT_HOME/webapp2/ROOT/WEB-INF/web.xml

Step 3: Repeat step 2.2.1 to localhost3 of www.mypmu.com, add <distributable/> into $TOMCAT_HOME/webapp2/ROOT/WEB-INF/web.xml

Clone tomcat #

Copy all content of directory $TOMCAT_HOME to another tomcat2

In Linux:

 cp -dpr tomcat tomcat2

Port numbers #

Change port numbers of tomcat2/conf/server.xml in order to make difference from the previous Tomcat:

 <Server port="8006" shutdown="SHUTDOWN">
   <Listener className="org.apache.catalina.core.AprLifecycleListener" />
   <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
   <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
   <Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener"/>
   <!-- Global JNDI resources -->
   <GlobalNamingResources>
     <Environment name="simpleValue" type="java.lang.Integer" value="30"/>
     <Resource name="UserDatabase" auth="Container"
               type="org.apache.catalina.UserDatabase"
        description="User database that can be updated and saved"
            factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
           pathname="conf/tomcat-users.xml" />
   </GlobalNamingResources>
   <Service name="Catalina">
     <Connector port="8081" maxHttpHeaderSize="8192"
                maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
                enableLookups="false" redirectPort="8444" acceptCount="100"
                connectionTimeout="20000" disableUploadTimeout="true"
 			   URIEncoding="UTF-8" />
     <Connector port="8010" 
                enableLookups="false" redirectPort="8444" protocol="AJP/1.3"
 			   URIEncoding="UTF-8" />
     <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm02">
       <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
              resourceName="UserDatabase"/>
       <Host name="localhost" appBase="webapps"
        unpackWARs="true" autoDeploy="true"
        xmlValidation="false" xmlNamespaceAware="false">
        	<Alias>www.mytcl.com</Alias>
        	<Alias>mytcl.com</Alias>        
         <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
                  managerClassName="org.apache.catalina.cluster.session.DeltaManager"
                  expireSessionsOnShutdown="false"
                  useDirtyFlag="true"
                  notifyListenersOnReplication="true">
             <Membership 
                 className="org.apache.catalina.cluster.mcast.McastService"
                 mcastAddr="228.0.0.4"
                 mcastPort="45564"
                 mcastFrequency="500"
                 mcastDropTime="3000"/>
             <Receiver 
                 className="org.apache.catalina.cluster.tcp.ReplicationListener"
                 tcpListenAddress="auto"
                 tcpListenPort="4004"
                 tcpSelectorTimeout="100"
                 tcpThreadCount="6"/>
             <Sender
                 className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
                 replicationMode="pooled"
                 ackTimeout="15000"
                 waitForAck="true"/>
             <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
                    filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
             <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
                       tempDir="/tmp/war-temp/"
                       deployDir="/tmp/war-deploy/"
                       watchDir="/tmp/war-listen/"
                       watchEnabled="false"/>
             <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
         </Cluster>
       </Host>
     </Engine>
   </Service>
 </Server>

Clustering in multiple hosting #

Add hosts for localhost2 of www.mytte.com and localhost3 of www.mypmu.com into tomcat2/conf/server.xml. Remember to make tcpListenPort difference from each other:

      <Host name="localhost3" debug="0" appBase="webapp3"
       unpackWARs="true" autoDeploy="true"
       xmlValidation="false" xmlNamespaceAware="false">
 	<Alias>www.mypmu.com</Alias>
 	<Alias>mypmu.com</Alias>
        <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
                 managerClassName="org.apache.catalina.cluster.session.DeltaManager"
                 expireSessionsOnShutdown="false"
                 useDirtyFlag="true"
                 notifyListenersOnReplication="true">
            <Membership 
                className="org.apache.catalina.cluster.mcast.McastService"
                mcastAddr="228.0.0.4"
                mcastPort="45564"
                mcastFrequency="500"
                mcastDropTime="3000"/>
            <Receiver 
                className="org.apache.catalina.cluster.tcp.ReplicationListener"
                tcpListenAddress="auto"
                tcpListenPort="4006"
                tcpSelectorTimeout="100"
                tcpThreadCount="6"/>
            <Sender
                className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
                replicationMode="pooled"
                ackTimeout="15000"
                waitForAck="true"/>
            <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
                   filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
            <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
                      tempDir="/tmp/war-temp/"
                      deployDir="/tmp/war-deploy/"
                      watchDir="/tmp/war-listen/"
                      watchEnabled="false"/>
            <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
        </Cluster>
      </Host>
      <Host name="localhost2" debug="0" appBase="webapp2"
       unpackWARs="true" autoDeploy="true"
       xmlValidation="false" xmlNamespaceAware="false">
 	<Alias>www.mytte.com</Alias>
 	<Alias>mytte.com</Alias>
        <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
                 managerClassName="org.apache.catalina.cluster.session.DeltaManager"
                 expireSessionsOnShutdown="false"
                 useDirtyFlag="true"
                 notifyListenersOnReplication="true">
            <Membership 
                className="org.apache.catalina.cluster.mcast.McastService"
                mcastAddr="228.0.0.4"
                mcastPort="45564"
                mcastFrequency="500"
                mcastDropTime="3000"/>
            <Receiver 
                className="org.apache.catalina.cluster.tcp.ReplicationListener"
                tcpListenAddress="auto"
                tcpListenPort="4005"
                tcpSelectorTimeout="100"
                tcpThreadCount="6"/>
            <Sender
                className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
                replicationMode="pooled"
                ackTimeout="15000"
                waitForAck="true"/>
            <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
                   filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
            <Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
                      tempDir="/tmp/war-temp/"
                      deployDir="/tmp/war-deploy/"
                      watchDir="/tmp/war-listen/"
                      watchEnabled="false"/>
            <ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
        </Cluster>
      </Host>

Route in Linux #

If the cluster dosen't work under linux with two nodes at two boxes, Check the following:

1) Is your network interface enabled for multicast? ifconfig eth0 MULICAST

2) Exists a multicast route to your network interface? My settting is: route add -host 228.0.0.4 gw 192.168.10.10 dev eth0

3) Is your firewall active? Then check if that multicast port is on your UDP open list and the receiver TCP port is also open for both machines!

My fair share #

Finally, you can start both tomcat machines. You should now be able to see in their logs and that they are communicating as a cluster (example is http://192.168.10.11:8080 and http://192.168.10.12:8081)

And you may check their session replication by using the below test.jsp:

 <%@ page contentType="text/html; charset=UTF-8" import="java.util.*"%>
 <html><head><title>Cluster App Test</title></head>
 <body>
 Server Info: <%out.print(request.getLocalAddr() + " : " + request.getLocalPort());%>
 <%
   out.println(" ID " + session.getId());
   String dataName = request.getParameter("dataName");
   if (dataName != null && dataName.length() > 0) {
      String dataValue = request.getParameter("dataValue");
      session.setAttribute(dataName, dataValue);
   }
   Enumeration e = session.getAttributeNames();
   while (e.hasMoreElements()) {
      String name = (String)e.nextElement();
      String value = session.getAttribute(name).toString();
      out.println( name + " = " + value);
    }
 %>
   <form action="test.jsp" method="POST">
     Name:<input type=text size=20 name="dataName">
      
     Value:<input type=text size=20 name="dataValue">
      
     <input type=submit>
    </form>
 </body>
 </html>

Reference #

http://tomcat.apache.org/tomcat-5.5-doc/cluster-howto.html

http://tomcat.apache.org/faq/cluster.html

http://www.theserverside.com/tt/articles/article.tss?l=ClusteringTomcat

Load Balancing #

Tomcat doesn’t provide the failover capability to redirect any incoming requests to the next available server in case one of the cluster nodes goes down. Hence a load balancer takes care of workload balance and failover. There is two popular load balancers in open source market:

Solution 1: Apache + mod_jk (Reference: http://howtoforge.com/high_availability_loadbalanced_apache_cluster)

Solution 2: Pen is a load balancer for "simple" tcp based protocols such as http or smtp. It allows several servers to appear as one to the outside and automatically detects servers that are down and distributes clients among the available servers. This gives high availability and scalable performance. (Reference: http://siag.nu/pen/)

The difference between Apache+mod_jk and Pen is that installation and operation of Pen is much more simple than Apache+mod_jk.

Download #

Download website: http://siag.nu/pub/pen/pen-0.17.1.tar.gz Unzip files:

 tar zxvf pen-0.17.1.tar.gz

Installation #

For Linux, type:

 ./configure
 make
 make install

For Windows, you have just downloaded it from http://siag.nu/pub/pen/pen-0.17.1.exe

Running #

The command to run the load balancer is as follows:

 pen -f -a -d -w localhost:80 192.168.10.11:8080 192.168.10.12:8081 

The following is the explanation of above command-line parameter used to launch the load balancer.

 -w: Use weight algorithm for load balancing
 -a: Prints the data sent back and forth in ASCII format
 -f: Stay in foreground
 -d: Enable debug mode 

Reference #

http://siag.nu/pen/

http://siag.nu/pen/vrrpd-linux.shtml

Database Clustering #

Sequoia is an open source database clustering middleware that allows any Java application to transparently access a cluster of databases through JDBC.

The following example will be shown Liferay and Sequoia working together, we use HSQLDB as the database sample.

Installation #

Step 1: Download sequoia-2.10.2-bin.zip from http://sequoia.continuent.org

Step 2: Unzip sequoia-2.10.2-bin.zip to your favourite directory (example: /home/brian/sequoia)

Step 3: Set up environment:

In Linux:

 export SEQUOIA_HOME=/home/brian/sequoia
 export CLASSPATH_XTRAS=/home/brian/sequoia/3rdparty/hsqldb/lib/hsqldb.jar

In Windows:

 set SEQUOIA_HOME=C:\home\brian\sequoia
 set CLASSPATH_XTRAS=C:\sequoia\3rdparty\hsqldb\lib\hsqldb.jar

HSQLDB schema #

Step 1: Bugfix of Sequoia for HSQLDB

Modify file: $SEQUOIA_HOME/lib/octopus/xml/conf/HypersonicSQLConf.xml

Bugfix 1: Add BOOLEAN between tag “SQLType” like below:

 	<SQLType>
 		<BOOLEAN javaType="java.lang.Boolean">BOOLEAN</BOOLEAN>
 	</SQLType>

Bugfix 2: Modify BOOLEAN between tag “JDBCType” like below:

 	<JDBCType>>
 		<BOOLEAN>BOOLEAN</BOOLEAN>
 	</JDBCType>

Step 2: OctopusDBVendors.xml

Modify file $SEQUOIA_HOME/lib/octopus/xml/conf/OctopusDBVendors.xml

Keep below databases, others may be commented.

 	 <Vendor name="Csv">CsvConf.xml</Vendor>
 	 <Vendor name="HypersonicSQL">HypersonicSQLConf.xml</Vendor>

Step 3: Virtual databases of Liferay

 mkdir $HOME/hsqldb1
 cp $TOMCAT_HOME/bin/test.*
 cd $HOME/hsqldb1
 java -cp hsqldb.jar org.hsqldb.Server -port 9001
 mkdir $HOME/hsqldb2
 cp $TOMCAT_HOME/bin/test.* $HOME/hsqldb2
 cd $HOME/hsqldb2
 java -cp hsqldb.jar org.hsqldb.Server -port 9002

Step 4: Recovery log database of Sequoia

 mkdir $HOME/hsqldb3
 cp $SEQUOIA_HOME/3rdparty/hsqldb/data/test.* $HOME/hsqldb3 
 cd $HOME/hsqldb3
 java -cp hsqldb.jar org.hsqldb.Server -port 9003

Step 5: It is an option to repeat step 1 to step 3 to create virtual databases from port 9004 to 9006 similarly

Step 6: Sequoia is flexible to distribute all databases to different machines, see above diagram:

Controller 1 is assigned to 192.168.10.19

Database 1 is assigned to 192.168.10.13

Database 2 is assigned to 192.168.10.14

Recovery log 1 is assigned to 192.168.10.15

Controller 2 is assigned to 192.168.10.20

Database 3 is assigned to 192.168.10.16

Database 4 is assigned to 192.168.10.17

Recovery log 2 is assigned to 192.168.10.18

Configure controllers #

Step 1: Create controller file $SEQUOIA_HOME/config/controller/liferayController1.xml as belows:

 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE SEQUOIA-CONTROLLER PUBLIC "-//Continuent//DTD SEQUOIA-CONTROLLER 2.10.2//EN"  "http://sequoia.continuent.org/dtds/sequoia-controller-2.10.2.dtd">
 <SEQUOIA-CONTROLLER>
 	<Controller ipAddress="192.168.10.19" port="25322">
     <JmxSettings>
     	<RmiJmxAdaptor port="1090"/>
 	</JmxSettings>
 	<VirtualDatabase configFile="liferayVDB1.xml" virtualDatabaseName="lportal" autoEnableBackends="true"/>
 	</Controller>
 </SEQUOIA-CONTROLLER>

Step 2: Repeat step 1 to create another controller $SEQUOIA_HOME/config/controller/liferayController2.xml as belows:

 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE SEQUOIA-CONTROLLER PUBLIC "-//Continuent//DTD SEQUOIA-CONTROLLER 2.10.2//EN"  "http://sequoia.continuent.org/dtds/sequoia-controller-2.10.2.dtd">
 <SEQUOIA-CONTROLLER>
 	<Controller ipAddress="192.168.10.20" port="25323">
     <JmxSettings>
     	<RmiJmxAdaptor port="1091"/>
 	</JmxSettings>
 	<VirtualDatabase configFile="liferayVDB2.xml" virtualDatabaseName="lportal" autoEnableBackends="true"/>
 	</Controller>
 </SEQUOIA-CONTROLLER>

Configure virtual databases #

Step 1: Create virtual database file $SEQUOIA_HOME/config/virtualdatabase/liferayVDB1.xml as below:

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE SEQUOIA PUBLIC "-//Continuent//DTD SEQUOIA 2.10.2//EN" "http://sequoia.continuent.org/dtds/sequoia-2.10.2.dtd">
 <SEQUOIA>
  <VirtualDatabase name="lportal">
 	<Distribution>
 	 <MessageTimeouts/>
 	</Distribution>
    <Backup>
      <Backuper backuperName="Octopus"
        className="org.continuent.sequoia.controller.backup.backupers.OctopusBackuper"
        options="zip=true"/>
    </Backup>   
   <AuthenticationManager>
      <Admin>
      	<User username="admin" password="adminPassword"/>
      </Admin> 
      <VirtualUsers>
        <VirtualLogin vLogin="user" vPassword="userPassord"/>
      </VirtualUsers>
    </AuthenticationManager>
    <DatabaseBackend name="database1" driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://192.168.10.13:9001" connectionTestStatement="call now()">
      <ConnectionManager vLogin="user" rLogin="sa" rPassword="">
        <VariablePoolConnectionManager initPoolSize="10" minPoolSize="5" maxPoolSize="50" idleTimeout="30" waitTimeout="10"/>
      </ConnectionManager>
    </DatabaseBackend>
    <DatabaseBackend name="database2" driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://192.168.10.14:9002" connectionTestStatement="call now()">
      <ConnectionManager vLogin="user" rLogin="sa" rPassword="">
        <VariablePoolConnectionManager initPoolSize="10" minPoolSize="5" maxPoolSize="50" idleTimeout="30" waitTimeout="10"/>
      </ConnectionManager>
    </DatabaseBackend>
    <RequestManager>
      <RequestScheduler>
         <RAIDb-1Scheduler level="passThrough"/>
      </RequestScheduler>
      <LoadBalancer>
         <RAIDb-1>
            <WaitForCompletion policy="first"/>
            <RAIDb-1-LeastPendingRequestsFirst/>
         </RAIDb-1>
      </LoadBalancer>
      <RecoveryLog driver="org.hsqldb.jdbcDriver"
        url="jdbc:hsqldb:hsql://192.168.10.15:9003" login="sa" password="">
        <RecoveryLogTable tableName="RECOVERY" logIdColumnType="BIGINT NOT NULL"
          vloginColumnType="VARCHAR NOT NULL" sqlColumnType="VARCHAR NOT NULL"
          extraStatementDefinition=",PRIMARY KEY (log_id)"/>
        <CheckpointTable tableName="CHECKPOINT"
          checkpointNameColumnType="VARCHAR NOT NULL"/>
        <BackendTable tableName="BACKEND"
          databaseNameColumnType="VARCHAR NOT NULL"
          backendNameColumnType="VARCHAR NOT NULL"
          checkpointNameColumnType="VARCHAR NOT NULL"/>
        <DumpTable tableName="DUMP" dumpNameColumnType="VARCHAR NOT NULL"
          dumpDateColumnType="TIMESTAMP"
          dumpPathColumnType="VARCHAR NOT NULL"
          dumpFormatColumnType="VARCHAR NOT NULL"
          checkpointNameColumnType="VARCHAR NOT NULL"
          backendNameColumnType="VARCHAR NOT NULL"
          tablesColumnType="VARCHAR NOT NULL"/>
      </RecoveryLog>
    </RequestManager>
  </VirtualDatabase>
 </SEQUOIA>

Step 2: Repeat step 1 to create another virtual database file $SEQUOIA_HOME/config/virtualdatabase/liferayVDB2.xml as below:

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE SEQUOIA PUBLIC "-//Continuent//DTD SEQUOIA 2.10.2//EN" "http://sequoia.continuent.org/dtds/sequoia-2.10.2.dtd">
 <SEQUOIA>
  <VirtualDatabase name="lportal">
 	<Distribution>
 	 <MessageTimeouts/>
 	</Distribution>
    <Backup>
      <Backuper backuperName="Octopus"
        className="org.continuent.sequoia.controller.backup.backupers.OctopusBackuper"
        options="zip=true"/>
    </Backup>   
   <AuthenticationManager>
      <Admin>
      	<User username="admin" password="adminPassword"/>
      </Admin> 
      <VirtualUsers>
        <VirtualLogin vLogin="user" vPassword="userPassord"/>
      </VirtualUsers>
    </AuthenticationManager>
    <DatabaseBackend name="database3" driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://192.168.10.13:9004" connectionTestStatement="call now()">
      <ConnectionManager vLogin="user" rLogin="sa" rPassword="">
        <VariablePoolConnectionManager initPoolSize="10" minPoolSize="5" maxPoolSize="50" idleTimeout="30" waitTimeout="10"/>
      </ConnectionManager>
    </DatabaseBackend>
    <DatabaseBackend name="database4" driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://192.168.10.14:9005" connectionTestStatement="call now()">
      <ConnectionManager vLogin="user" rLogin="sa" rPassword="">
        <VariablePoolConnectionManager initPoolSize="10" minPoolSize="5" maxPoolSize="50" idleTimeout="30" waitTimeout="10"/>
      </ConnectionManager>
    </DatabaseBackend>
    <RequestManager>
      <RequestScheduler>
         <RAIDb-1Scheduler level="passThrough"/>
      </RequestScheduler>
      <LoadBalancer>
         <RAIDb-1>
            <WaitForCompletion policy="first"/>
            <RAIDb-1-LeastPendingRequestsFirst/>
         </RAIDb-1>
      </LoadBalancer>
      <RecoveryLog driver="org.hsqldb.jdbcDriver"
        url="jdbc:hsqldb:hsql://192.168.10.15:9006" login="sa" password="">
        <RecoveryLogTable tableName="RECOVERY" logIdColumnType="BIGINT NOT NULL"
          vloginColumnType="VARCHAR NOT NULL" sqlColumnType="VARCHAR NOT NULL"
          extraStatementDefinition=",PRIMARY KEY (log_id)"/>
        <CheckpointTable tableName="CHECKPOINT"
          checkpointNameColumnType="VARCHAR NOT NULL"/>
        <BackendTable tableName="BACKEND"
          databaseNameColumnType="VARCHAR NOT NULL"
          backendNameColumnType="VARCHAR NOT NULL"
          checkpointNameColumnType="VARCHAR NOT NULL"/>
        <DumpTable tableName="DUMP" dumpNameColumnType="VARCHAR NOT NULL"
          dumpDateColumnType="TIMESTAMP"
          dumpPathColumnType="VARCHAR NOT NULL"
          dumpFormatColumnType="VARCHAR NOT NULL"
          checkpointNameColumnType="VARCHAR NOT NULL"
          backendNameColumnType="VARCHAR NOT NULL"
          tablesColumnType="VARCHAR NOT NULL"/>
      </RecoveryLog>
    </RequestManager>
  </VirtualDatabase>
 </SEQUOIA>

Start Controller #

Step 1: $SEQUOIA_HOME/bin/controller.sh -f ../config/controller/liferayController1.xml

Step 2: $SEQUOIA_HOME/bin/controller.sh -f ../config/controller/liferayController2.xml

Step 3: Thie step is required to ininitialize virtual databases at the first time only

In Linux: $SEQUOIA_HOME/bin/console.sh

In Windows: %SEQUOIA_HOME%/bin/console.bat

type:

 		admin lportal
 		admin
 		adminPassword
 		expert on
 		initialize database1
 		backup database1 backup1 Octopus .
 		sa
 		enable database1
 		restore backend database2 backup1
 		sa
 		enable database2
 		restore backend database3 backup1
 		sa
 		enable database3
 		restore backend database4 backup1
 		sa
 		enable database4
 		show backend *
 		quit
 		quit

Liferay configuration #

Step 1: JDBC Driver

copy $SEQUOIA_HOME/drivers/sequoia-driver.jar to $TOMCAT_HOME/common/lib/ext

Step 2: ROOT.xml

Connect Sequoia virtual databases, clustering jdbc is scalarable to cluster one to many database connection:

 Virtual database 1: 192.168.10.19
 Virtual database 2: 192.168.10.20

Modify file $TOMCAT_HOME/conf/Catalina/localhost/ROOT.xml

        <Resource
                name="jdbc/LiferayPool"
                auth="Container"
                type="javax.sql.DataSource"
                driverClassName="org.continuent.sequoia.driver.Driver"
                url="jdbc:sequoia://192.168.10.19:25322,192.168.10.20:25323/lportal"
                username="user"
                password="userPassword"
                maxActive="20"
        />

Step 3: portal-ext.properties

Add below statement to $TOMCAT_HOME/webapps/ROOT/WEB-INF/classes/portal-ext.properties

 hibernate.dialect=org.hibernate.dialect.HSQLDialect

Start Tomcat #

In Linux, start Liferay at $TOMCAT_HOME/bin/startup.sh

In Windows, %TOMCAT_HOME%/bin/startup.bat

Shutdown procedure #

Step 1: Shutdown Liferay:

In Linux, $TOMCAT_HOME/bin/shutdown.sh

In Windows, %TOMCAT_HOME%/bin/shutdown.bat

Step 2: Shutdown Sequoia:

In Linux, $SEQUOIA_HOME/bin/console.sh

In Windows, %SEQUOIA_HOME%/bin/console.bat

type:

 		shutdown virtualdatabase lportal
 		shutdown
 		quit

Reference #

http://sequoia.continuent.org/HomePage

http://www.onlamp.com/pub/wlg/7963

Dynamic Virtual Hosting #

Liferay provides a new dynamic virtual hosting model starting with version 4.2. New dynamic virtual hosting will let you to add virtual hosts without restarting tomcat. All hosts are served by the same webapps.

Related Articles #

Clustering

Using Terracota with Liferay

0 Attachments
127918 Views
Average (4 Votes)
The average rating is 5.0 stars out of 5.
Comments
Threaded Replies Author Date
Very interesting and informative article. And... Ziggy © August 14, 2009 4:44 AM
One querry:How to modify compnay_it to... Chirag Suthar November 3, 2009 5:13 AM
Hi I have also face the same problem but i get ... DarshanKumar N Bhatia April 28, 2010 5:02 AM
Great article Thanks a lot Juan Fernández December 11, 2009 3:23 AM
Hi, Is it possible to host the liferay portal... Kachara Raj January 23, 2010 9:56 PM
Yes, it is possible to distribute via VPN. By... Shepherd Ching March 13, 2010 2:27 AM
Thanks a lot for Sharing this information. Pravin Pawar March 30, 2010 6:35 AM
Yaa I got same question : where to find same... DarshanKumar N Bhatia April 28, 2010 12:08 AM
a very good howto. I'm going to test it. Leon Z December 20, 2011 4:57 AM
I try to setup virtual on liferay 6.0.5 and... linh truongthe December 5, 2012 6:42 PM

Very interesting and informative article. And thanks for the time you've put into it.
Posted on 8/14/09 4:44 AM.
One querry:How to modify compnay_it to abcd.com.I am not able to find any company_id in web.xml.

" "Step 3: Edit $TOMCAT_HOME/webapp2/ROOT/WEB-INF/web.xml modify the company_id to mytte.com " "

Please suggest me.
Posted on 11/3/09 5:13 AM.
Great article
Thanks a lot
Posted on 12/11/09 3:23 AM.
Hi,

Is it possible to host the liferay portal with distributed deployments? The primary reason for this it to host a world wide portal that's deployed in Asia, Europe and US at the same time.
We can work with DB vendor to get the multi-master replication, but wanted to know if there are any known issues (e.g. caching implementation etc.) that will prohibit such deployment model?

Thanks,

Raj
Posted on 1/23/10 9:56 PM.
Yes, it is possible to distribute via VPN.

By the way, this wiki introduces Tomcat SimpleTCPCluster method which is mainly for Liferay version 4.0.0 or before.

I advise you to read this blog for newer Liferay versions:
http://www.liferay.com/web/ivan.cheung/blog/-/blogs/clustering-liferay-tomcat-my­sql-on-windows-xp?_33_redirect=%2Fweb%2Fivan.cheung%2Fblog
Posted on 3/13/10 2:27 AM in reply to Kachara Raj.
Thanks a lot for Sharing this information.
Posted on 3/30/10 6:35 AM in reply to Shepherd Ching.
Yaa I got same question :
where to find same information for liferay5.2.3 with tomcat5.5.
How to modify compnay_it to abcd.com.
I am not able to find any company_id in web.xml.

" "Step 3: Edit $TOMCAT_HOME/webapp2/ROOT/WEB-INF/web.xml modify the company_id to mytte.com " "
Posted on 4/28/10 12:08 AM.
Hi I have also face the same problem but i get
solution too
http://www.liferay.com/community/forums/-/message_boards/message/57646

check web.xml specification
and add
<context-param>
<param-name>company_id</param-name>
<param-value>liferay.com</para­m-value>
</context-param>
<context-param>

to web.xml it works properly.
I created three independent instance of liferay with same tomcat and single database.
Posted on 4/28/10 5:02 AM in reply to Chirag Suthar.
a very good howto. I'm going to test it.
Posted on 12/20/11 4:57 AM.
I try to setup virtual on liferay 6.0.5 and tomcat 6

When start tomcat this error occur:

org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [com.liferay.portal.dao.orm.hibernate.jmx.HibernateStatisticsService@1f28508] with key 'Hibernate:name=statistics'; nested exception is javax.management.InstanceAlreadyExistsException: Hibernate:name=statistics

Please help me.

Thanks
Posted on 12/5/12 6:42 PM in reply to liang zhang.