aspose file tools*
The moose likes Threads and Synchronization and the fly likes Sudden Logout Problem - Related to Concurrency? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Sudden Logout Problem - Related to Concurrency?" Watch "Sudden Logout Problem - Related to Concurrency?" New topic
Author

Sudden Logout Problem - Related to Concurrency?

Harish Verma
Ranch Hand

Joined: Feb 27, 2006
Posts: 32
Hello folks, I am investigating an issue on the Production server in our Struts-based app running on a clustered OAS environment.

Struts ActionClass is defined as a singleton, which means the ActionClass will be created only once and will create a new thread for each incoming request, and call the execute() method. In our implementation, in the execute(...) method, we are instantiating an object that contains several static and non-static methods.


So, since s is a per-thread instance of ShareableCode class, any calls to its static and non-static methods must be implicitly thread-safe, since each thread instantiated by the TwentyPointAction class has its own copy of s. The same must be the case in a clustered, multiprocessor environment too. Am I correct? THe problem is I am facing is sudden, inexplicable logouts under severe load conditions. These seem to happen when the request's session ID does not match up with the session's ID. That is, request.isRequestedSessionIdValid() returns false, since request.getRequestedSessionId() does not match request.getSession(false).getId(). When the sudden logout appears, request.getSession(false).getId() returns a new value that has never appeared before in the logs. I think session-replication timeout is probably the issue, but just want to be sure that the non-synchronized isValidUser() method is not getting its request and session objects mixed-up due to concurrency issues.

In general, are method calls to static and non-static methods of a class threadsafe if we ensure that the calling thread instantiates its own copy of that class, and ensure that no shared resource is read or updated?

TIA for your help.
Harish Verma
Ranch Hand

Joined: Feb 27, 2006
Posts: 32
Apologies for multiple post creations. I received an error each time I tried to submit and assumed the post didnt make it; but I was wrong and now I see multiple threads in this forum. Apologies again and request admin cleanup. Thanks.
Harish Verma
Ranch Hand

Joined: Feb 27, 2006
Posts: 32
I am adding some more info about this problem.





The log shows the following:
[08.07.2009 15:51:32]-[INFO]-[6]-[ShareableCode]-[isValidUser(): The incoming request contains this session ID: ac10138830fccbac6f25ef034679a9d6d48cfda6ed76]

[08.07.2009 15:51:32]-[INFO]-[6]-[ShareableCode]-[isValidUser(): request.getSession(false) returned a session object with ID=ac10138930fc8cfaed30e56a4df7918aa0cb964cb6c3]

[08.07.2009 15:51:32]-[ERROR]-[6]-[ShareableCode]-[isValidUser(): session.isNew() returned TRUE - the client has probably turned off cookies.]

ac10138830fccbac6f25ef034679a9d6d48cfda6ed76 - this is the session assigned to the user after login.
ac10138930fc8cfaed30e56a4df7918aa0cb964cb6c3 - this appears out of nowhere, 'mapped' to this request.

And so the user ends up at login again, despite having logged in barely a minute ago.

The request is 'wrapped' to another, new session object, despite the presence of the session created during login. Note that request.isRequestedSessionIdValid() is returning TRUE - that's why the code skips to if (session.isNew()) block.

if request.isRequestedSessionIdValid() is true, how come the request is 'wrapped' into a different session? I have googled widely, but cannot pin down where the problem is - Struts, OAS server, or our application code.

Any help is appreciated. TIA.
Harish
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Hi Harish,

I don't have any familiarity with your system, and very little familiarity with clustering. This question does not appear to be a problem with Threads and Concurrency by itself, but seems more likely caused by clustering/JEE setup and configuration.

Like I said I have no real experience in this area, but I would research 2 things:
1) The session id that is requested is not the same as the one that is returned. This could be because, under high load, the request for any specific user may not be going to the same server. When it gets to the new server the session doesn't exist, so it has to be pulled from whatever store is shared between the clustered servers. This might mean that a new Session ID is assigned. I would check if this is what is happening.

2) If this is the case, it might be that relying on the Session ID to check for current login may not be appropriate. Instead, when a user completes logging in, put a token in the session. Then when you check for valid login simply check for this token. It looks like you might already be doing this with the session.getArrtibute("objUserProfile") check. So one thing to try would be to simplify this entire thing: get rid of the session id checks entirely. The goal, after all is to see if the user is logged in, so check for the token. If it is there, the user is logged in, if not, then the user is not logged in.


Steve
Harish Verma
Ranch Hand

Joined: Feb 27, 2006
Posts: 32
Steve Luke wrote:Hi Harish,

I don't have any familiarity with your system, and very little familiarity with clustering. This question does not appear to be a problem with Threads and Concurrency by itself, but seems more likely caused by clustering/JEE setup and configuration.

Like I said I have no real experience in this area, but I would research 2 things:
1) The session id that is requested is not the same as the one that is returned. This could be because, under high load, the request for any specific user may not be going to the same server. When it gets to the new server the session doesn't exist, so it has to be pulled from whatever store is shared between the clustered servers. This might mean that a new Session ID is assigned. I would check if this is what is happening.

2) If this is the case, it might be that relying on the Session ID to check for current login may not be appropriate. Instead, when a user completes logging in, put a token in the session. Then when you check for valid login simply check for this token. It looks like you might already be doing this with the session.getArrtibute("objUserProfile") check. So one thing to try would be to simplify this entire thing: get rid of the session id checks entirely. The goal, after all is to see if the user is logged in, so check for the token. If it is there, the user is logged in, if not, then the user is not logged in.

Thanks much Steve for your suggestions. There is no store as such that is shared between the servers in the cluster. We rely entirely on the replication process to do the needful for us. Somewhere down the line, the requested session is missing and the server container gives us a new one. In this scenario, getting rid of all the ID checks does not help; the session is brand-new and ofcourse does not contain objUserProfile, so the condition fails anyway and we end up at login. I guess I'll have to ask the client to upgrade their hardware - this is going to get unpleasant. :cry:
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Sudden Logout Problem - Related to Concurrency?