Blogs
This is assumed in the article that Liferay DXP Clustering between 2
nodes is working properly and both nodes can communicate with each
other.
What is Session Replication?
In simple words, session replication ensures that if a client connection fails over from one server to another the state of the client session is maintained.
The entire client session data is copied on a replicated instance. However, the session replication operation does not copy the attributes that cannot be serialized in a session and any instance-specific data.
Session replication along with load balancing provides good failover capabilities.
However, since the blog is primarily concerned with configuring session replication, we won't go into the advantages and disadvantages of session replication.
Simplified Architecture Diagram:
The below-mentioned steps will be common for both nodes. (All the steps must be followed in both Liferay Nodes).
Step #1
Go to liferay_home/tomcat-9.x.x/conf
file and open
the server.xml
file Search for the below tag
<Engine name="Catalina" defaultHost="localhost" >
Add the jvmRoute attribue inside it jvmRoute="workerX" , the modified tag will look like below:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="workerX">
Note: replace X in workerX with the desired node number viz: 1,2 etc
Step #2
In the server.xml file search for the below tag
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
Below this line add the TCP cluster configuration
<Cluster
className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager
className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel
className="org.apache.catalina.tribes.group.GroupChannel">
<Sender
className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport
className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Receiver
className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="CurrentLiferayServerNodeIP"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Interceptor
className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor
className="org.apache.catalina.tribes.group.interceptors.StaticMembershipInterceptor">
<Member
className="org.apache.catalina.tribes.membership.StaticMember"
port="4000"
securePort="-1"
host="AnotherLiferayServerNodeIP"
domain="staging-cluster"
uniqueId="{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}"/>
</Interceptor>
</Channel>
<Valve
className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve
className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<ClusterListener
className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
Make sure port 4000 is open
and is not restricted by a firewall for both nodes. (You can change
the port number to other desired TCP port number, if required)
Step #3
Enabling tomcat clustering logs which will be stored in
tomcat-9.x.x/logs
directory with name
ha.yyyy-mm-dd.log
Open the tomcat-9.x.x/conf/logging.properties
and
modify the below changes for handlers and
.handlers
handlers = 1catalina.org.apache.juli.AsyncFileHandler,
2localhost.org.apache.juli.AsyncFileHandler,
3manager.org.apache.juli.AsyncFileHandler,
4host-manager.org.apache.juli.AsyncFileHandler,
java.util.logging.ConsoleHandler,
5cluster.org.apache.juli.FileHandler,
6cluster.org.apache.juli.FileHandler
.handlers = 1catalina.org.apache.juli.AsyncFileHandler,
java.util.logging.ConsoleHandler,
5cluster.org.apache.juli.FileHandler
Add the below lines at the end of the same file logging.properties to enable INFO logs in log files
5cluster.org.apache.juli.FileHandler.level = INFO
5cluster.org.apache.juli.FileHandler.directory =
${catalina.base}/logs
5cluster.org.apache.juli.FileHandler.prefix = cluster.
6cluster.org.apache.juli.FileHandler.level = INFO
6cluster.org.apache.juli.FileHandler.directory =
${catalina.base}/logs
6cluster.org.apache.juli.FileHandler.prefix = ha.
org.apache.catalina.tribes.MESSAGES.level = INFO
org.apache.catalina.tribes.MESSAGES.handlers =
5cluster.org.apache.juli.FileHandler
org.apache.catalina.tribes.level = INFO
org.apache.catalina.tribes.handlers =
5cluster.org.apache.juli.FileHandler
org.apache.catalina.ha.level = INFO
org.apache.catalina.ha.handlers =
6cluster.org.apache.juli.FileHandler
Save and Exit the file
Step #4
Go to tomcat-9.x.x/webapps/ROOT/WEB-INF/
and open
web.xml
Inside the <web-app>
tag add
the <distributable/>
tag like below
Save and Exit the file.
Step #5
Add the below property to the portal-ext.properties
file to enable portlet session replication
portlet.session.replicate.enabled=true
Save and exit the file
Step #6
Validating the Session Replication
- Start Liferay Node 1, make sure it is fully UP and running, then start Liferay Node 2.
- Once both are Up and running, test the session replication functionality by logging into the portal from any node in Browser.
- Note down the JSESSION ID post login and the workerX from JSESSION ID cookie.
- Shut down the node on which Login happened, in the browser, URL change the IP address and Port to the other node's IP address and Port, keep rest of the URL same.
- Hit the Enter button, you will notice that you are still logged in and continue the session on another node as well.
NOTE: In case you are logged out in the above step and shown a URL not found error, that indicates that the session replication is not configured. Check the firewall, logs to debug further.
If you are getting error like the following:
'exmapleBean' attribute with type 'com.demo.portlet.example.' cannot be replicated
at org.jboss.as.web.session.ClusteredSession.setAttribute(ClusteredSession.java:824)
at org.apache.catalina.session.StandardSessionFacade.setAttribute(StandardSessionFacade.java:130)
at com.liferay.portlet.PortletSessionImpl.setAttribute(PortletSessionImpl.java:200)
Make sure all session objects and their attributes/variables are made Serializable.