Tomcat Session Clustering

Hi Guys,

I wanted to set up a small cluster between 2 lucee 5 (express) nodes. Set
up Tomcat clustering, marked the apps as distributable and changed lucee
sessions to JEE. Everything seems to work, except deserialising session
information received from another node:

org.apache.catalina.ha.session.DeltaManager.messageReceived Manager
[/context]: Unable to receive message through TCP channel
java.lang.ClassNotFoundException: lucee.runtime.type.scope.JSession
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at java.io.ObjectInputStream.resolveClass(Unknown Source)
at
org.apache.catalina.tribes.io.ReplicationStream.resolveClass(ReplicationStream.java:76)

I know, that there is the possibility to replicate sessions using a third
party cache like redis, but the lucee admin clearly states "JEE Sessions
allow to make sessions over a cluster. ". I am a little confused, since
serializing is working and i can see the seriilaized session via
javamelody.

Thanks in advance for clarifying this

The same Exception occurs, when Tomcat is persisting sessions locally in
the file system.Am Freitag, 17. Juni 2016 17:07:48 UTC+2 schrieb Martin Frstr:

Hi Guys,

I wanted to set up a small cluster between 2 lucee 5 (express) nodes. Set
up Tomcat clustering, marked the apps as distributable and changed lucee
sessions to JEE. Everything seems to work, except deserialising session
information received from another node:

org.apache.catalina.ha.session.DeltaManager.messageReceived Manager
[/context]: Unable to receive message through TCP channel
java.lang.ClassNotFoundException: lucee.runtime.type.scope.JSession
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at java.io.ObjectInputStream.resolveClass(Unknown Source)
at
org.apache.catalina.tribes.io.ReplicationStream.resolveClass(ReplicationStream.java:76)

I know, that there is the possibility to replicate sessions using a third
party cache like redis, but the lucee admin clearly states "JEE Sessions
allow to make sessions over a cluster. ". I am a little confused, since
serializing is working and i can see the seriilaized session via
javamelody.

Thanks in advance for clarifying this

Ok, maybe the title should be Deserialization of Lucee Sessions fails. So
this problem is not related to clustering in general, but to
deserialization of Lucee sessions, when using J2EE sessions. The JSession
class is not know to Tomcat and looking at its dependencies I guess this
issue is more complex than just letting tomcat know about the lucee classes.Am Freitag, 17. Juni 2016 17:07:48 UTC+2 schrieb Martin Frstr:

Hi Guys,

I wanted to set up a small cluster between 2 lucee 5 (express) nodes. Set
up Tomcat clustering, marked the apps as distributable and changed lucee
sessions to JEE. Everything seems to work, except deserialising session
information received from another node:

org.apache.catalina.ha.session.DeltaManager.messageReceived Manager
[/context]: Unable to receive message through TCP channel
java.lang.ClassNotFoundException: lucee.runtime.type.scope.JSession
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at java.io.ObjectInputStream.resolveClass(Unknown Source)
at
org.apache.catalina.tribes.io.ReplicationStream.resolveClass(ReplicationStream.java:76)

I know, that there is the possibility to replicate sessions using a third
party cache like redis, but the lucee admin clearly states "JEE Sessions
allow to make sessions over a cluster. ". I am a little confused, since
serializing is working and i can see the seriilaized session via
javamelody.

Thanks in advance for clarifying this

I remember this being an issue with Railo a while back.

I know you can store sessions in a db/cache and do session clustering without involving the servlet container.

Give me a sec and I shall try and get something going and document it (I know there is something out there tho)

MD> On 20 Jun 2016, at 11:55, ‘Martin Frstr’ via Lucee lucee@googlegroups.com wrote:

Ok, maybe the title should be Deserialization of Lucee Sessions fails. So this problem is not related to clustering in general, but to deserialization of Lucee sessions, when using J2EE sessions. The JSession class is not know to Tomcat and looking at its dependencies I guess this issue is more complex than just letting tomcat know about the lucee classes.

Am Freitag, 17. Juni 2016 17:07:48 UTC+2 schrieb Martin Frstr:
Hi Guys,

I wanted to set up a small cluster between 2 lucee 5 (express) nodes. Set up Tomcat clustering, marked the apps as distributable and changed lucee sessions to JEE. Everything seems to work, except deserialising session information received from another node:

org.apache.catalina.ha.session.DeltaManager.messageReceived Manager [/context]: Unable to receive message through TCP channel
java.lang.ClassNotFoundException: lucee.runtime.type.scope.JSession
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at java.io.ObjectInputStream.resolveClass(Unknown Source)
at org.apache.catalina.tribes.io.ReplicationStream.resolveClass(ReplicationStream.java:76)

I know, that there is the possibility to replicate sessions using a third party cache like redis, but the lucee admin clearly states "JEE Sessions allow to make sessions over a cluster. ". I am a little confused, since serializing is working and i can see the seriilaized session via javamelody.

Thanks in advance for clarifying this


Win a ticket to dev.objective from Lucee via Twitter, see http://bit.ly/1UbTMWj http://bit.ly/1UbTMWj for details, good luck and see you there…

You received this message because you are subscribed to the Google Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+unsubscribe@googlegroups.com mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto:lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/28a17dbd-8292-4624-9720-6602c382226f%40googlegroups.com https://groups.google.com/d/msgid/lucee/28a17dbd-8292-4624-9720-6602c382226f%40googlegroups.com?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout.

Hey Mark,

that would be awesome. Thanks in advance! :slight_smile:

Will get to it tomorrow. Jet lag hit me today :confused:

Mark Drew

  • Sent by typing with my thumbs.> On 20 Jun 2016, at 17:47, ‘Martin Frstr’ via Lucee lucee@googlegroups.com wrote:

Hey Mark,

that would be awesome. Thanks in advance! :slight_smile:

Win a ticket to dev.objective from Lucee via Twitter, see http://bit.ly/1UbTMWj for details, good luck and see you there…

You received this message because you are subscribed to the Google Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/14ed7e77-f41e-4cd1-b88d-14b4aca21a1d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

OK, so to get session clustering you need to add some settings to your Application.cfc, here is an example of mine:
component {
this.name = “ClusterDemo”;
this.sessionType = “application”;

this.datasources["sessionData"] = {
  class: 'org.gjt.mm.mysql.Driver'
, connectionString: 'jdbc:mysql://localhost:3306/sessionData?useUnicode=true&characterEncoding=UTF-8&useLegacyDatetimeCode=true'
, username: ''
, password: ""

, storage:true // default: false
};

this.sessionManagement = true;
this.sessionStorage = "sessionData"
this.sessionCluster = true;

}

Going line by line:

  1. First set the application name, this is important to maintain the data correctly.
  2. this.sessionType: I am manually setting it to application rather than j2ee here
  3. here I create a datasource called sessionData. notice I set the storage:true so it can contain session data
  4. Then I setup this.sessionManagement=true (since I do want it to manage sessions)
  5. then I tell it where I want it to store sessions, in this case in the sessionData DSN I defined in 3
  6. Finally, I want it to cluster them across servers, so just set this.sessioncluster = true.

as long as both of your applications (and they should be the same one!) have this, you can put these servers in a cluster and not even have to do sticky sessions, but just round robin the requests and it all should maintain state.

The downside here is that the OnSessionEnd() method in Application.cfc won’t get triggered anymore since you never know WHEN the session would end as it is not up to each individual server to define that. You can still have something else that reaps the sessions by checking the table in the database which contains an expires column.

I hope this helps!

regards

Mark Drew> On 20 Jun 2016, at 17:47, ‘Martin Frstr’ via Lucee lucee@googlegroups.com wrote:

Hey Mark,

that would be awesome. Thanks in advance! :slight_smile:


Win a ticket to dev.objective from Lucee via Twitter, see http://bit.ly/1UbTMWj http://bit.ly/1UbTMWj for details, good luck and see you there…

You received this message because you are subscribed to the Google Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+unsubscribe@googlegroups.com mailto:lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com mailto:lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/14ed7e77-f41e-4cd1-b88d-14b4aca21a1d%40googlegroups.com https://groups.google.com/d/msgid/lucee/14ed7e77-f41e-4cd1-b88d-14b4aca21a1d%40googlegroups.com?utm_medium=email&utm_source=footer.
For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout.

Hi Mark,

thanks for your answer, but your setup involves a third party system, like
the redis setup I mentioned in my first post.

Wouldn’t it be possible to move the serialization/deserialization part to
lucee itself and hand over the session content as java.lang.String to its
underlying servlet and session implementation? So all issues would be gone
and lucee never has to be aware of servlet specific implementations
regarding sessions, since Strings can be handled by every implementation
easily.

That would be the idea but since Railo there has been this session serialisation bug. Hence the method of third party storage. This actually an GoodThing™ as you can scale even bigger and each instance doesn’t have to know anything about each other.

Mark Drew

  • Sent by typing with my thumbs.> On 22 Jun 2016, at 08:35, ‘Martin Frstr’ via Lucee lucee@googlegroups.com wrote:

Hi Mark,

thanks for your answer, but your setup involves a third party system, like the redis setup I mentioned in my first post.

Wouldn’t it be possible to move the serialization/deserialization part to lucee itself and hand over the session content as java.lang.String to its underlying servlet and session implementation? So all issues would be gone and lucee never has to be aware of servlet specific implementations regarding sessions, since Strings can be handled by every implementation easily.

Win a ticket to dev.objective from Lucee via Twitter, see http://bit.ly/1UbTMWj for details, good luck and see you there…

You received this message because you are subscribed to the Google Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/55ad1533-35ef-43e4-abad-cd1ec46b302b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Fair point indeed.

This was the original bug if I recall correctly:
https://issues.jboss.org/browse/RAILO-2645

It says resolved but might need to setup a replication of this somehow
(docker perhaps) that can then be tested

MDOn 4 July 2016 at 12:58:03, ‘Martin Frstr’ via Lucee (lucee@googlegroups.com) wrote:

Hi Mark,

in general I agree with your point, but in this case it’s not about
performance, but rather about HA. This means the session storage (redis or
mysql) also needs to be HA and this feels a bit too much for this scenario.
But thanks for clarifiying this.

Win a ticket to dev.objective from Lucee via Twitter, see
http://bit.ly/1UbTMWj for details, good luck and see you there…

You received this message because you are subscribed to the Google Groups
“Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an
email to lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/lucee/3440da69-e4a5-460d-b631-255fbc65a7d9%40googlegroups.com
https://groups.google.com/d/msgid/lucee/3440da69-e4a5-460d-b631-255fbc65a7d9%40googlegroups.com?utm_medium=email&utm_source=footer
.
For more options, visit https://groups.google.com/d/optout.

Hi Mark,

in general I agree with your point, but in this case it’s not about
performance, but rather about HA. This means the session storage (redis or
mysql) also needs to be HA and this feels a bit too much for this scenario.
But thanks for clarifiying this.

Hi Mark,

yes, it is resolved and I can confirm that serialization works. When I
inspect the sessions with java melody I can see all the serialized
information. But what is failing, is deserialization, because Tomcat cannot
find the railo or lucee classes. This is also mentioned in the last
comments of the bug you have linked. I was naively trying to introduce the
classes to Tomcat. It worked and this specific exception was gone, but the
lucee JSession class has some dependencies to the lucee PageContext and
other classes, so i got some new NullPointerExceptions. Of course, this is
not the way to go, but if there is any progress going on in the session
system to hand over already stringified objects as Java.lang.String to the
underlying servlet container, I would really appreciate it, since it will
make lucee more compatible with any servlet container, cause serialization
and deserialization of strings is an easy job for every implementation. It
would be nice of you could give some insights if this is on the lucee
agenda or not.

Thanks for the information and thanks for taking time to respond. I really
appreciate your support :slight_smile:

Regards

Martin

Hi Marc,

I was looking at the issues in Jira, but could not find any that is related
to this problem. Would be nice to get some insights on this.

Thanks in advance!

Hi Mark,

i was messing around with lucee Caches. EHCache is included and is capable
of being distributable and replicatable. So a simple eh cache setup with
distribution would leverage the same features as tomcat tribes offers,
without needing additional processes or services. Am I correct?

Thanks in advance!