Edmond Wang
Edmond Wang

Reputation: 1697

How to let Primary Session share "session time out" with Secondary Session on Weblogic?

Update question description to be more specified and detailed.

I have a weblogic 12c, configured with one cluster, 4 node instances in the cluster, Default Load Algorithm is Round Robin, Replication Type is MAN. I deploy one web application on all 4 nodes.

What I design at first time is:

Execute logout related business logic once user session got invalidated. Put logic code inside "sessionDestroyed" method of SessionListener.java which implements HttpSession Interface. As you know, session got invalidated could be caused by 2 case, one is manually logout, another is J2ee container trigger the time out. My issue is occurred because of the 2nd case.

Issue:

The business logic code inside "SessionDestroyed" event is executed twice for one user time out, which is not expected and result in business error. What I found is Primary Http Session on the node A and Backup Session on the node B both trigger the weblogic "SessionDestroyed" event.

Question:

  1. Why Backup Session on the node B trigger session timeout event although Primary Session on the node A has already been time out ?
  2. How to let Backup Session know that Primary Session has already been invalidated?

Attach the Log, you can see the first and second line is primary session, the third line is backup session, which can be proved by the session id in the line tail.

DEBUG Oct-20-17 01:53:40 [[ACTIVE] ExecuteThread: '9' for queue: 'weblogic.kernel.Default (self-tuning)'] (AMCSessionListener-27  ) - Session: wIc4WB62vlaYR_tMRMIc0WpBHchh5fbwpinxgaig4mJRJFhlPUcj!-1795465203!1400921280!1508478820022 Created at Fri Oct 20 01:53:40 EDT 2017
DEBUG Oct-20-17 02:54:05 [[ACTIVE] ExecuteThread: '9' for queue: 'weblogic.kernel.Default (self-tuning)'] (AMCSessionListener-46  ) - Session: wIc4WB62vlaYR_tMRMIc0WpBHchh5fbwpinxgaig4mJRJFhlPUcj!-1795465203!1400921280!1508478820022 Destroyed at Fri Oct 20 02:54:05 EDT 2017
DEBUG Oct-20-17 02:55:12 [[ACTIVE] ExecuteThread: '17' for queue: 'weblogic.kernel.Default (self-tuning)'] (AMCSessionListener-46  ) - Session: wIc4WB62vlaYR_tMRMIc0WpBHchh5fbwpinxgaig4mJRJFhlPUcj!173379423!1400921280!1508478820022 Destroyed at Fri Oct 20 02:55:12 EDT 2017

Below is my weblogic configuration:

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app
xmlns="http://www.bea.com/ns/weblogic/90"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-web-app.xsd">
  <session-descriptor>
    <cookie-path>/AppName</cookie-path>
    <persistent-store-type>replicated</persistent-store-type>
    <http-proxy-caching-of-cookies>true</http-proxy-caching-of-cookies>
    <cookie-secure>true</cookie-secure>   
  </session-descriptor>  
</weblogic-web-app>

This is my session configure in the web.xml inside web application:

<session-config>
    <session-timeout>60</session-timeout>
</session-config>

This is my SessionListener.java:

public class SessionListener implements HttpSessionListener {

    private static Logger logger = Logger.getLogger(SessionListener.class);

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        if (logger.isDebugEnabled()) {
            logger.debug("Session: " + se.getSession().getId() + " Created at " + (new java.util.Date()));
        }
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        /**
         * The business logic code related to logout action
         * would be executed twice here, this is not what I want.
         **/
        if (logger.isDebugEnabled()) {
            logger.debug("Session: " + se.getSession().getId() + " Destroyed at " + (new java.util.Date()));
        }
    }
}

This code for manually logout:

@RequestMapping(value = "/logout", method = RequestMethod.GET)
public ModelAndView logout(HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        ...
        // Business Logic for Logout
        ...

        request.getSession().invalidate();

        CommonViewObject vo = new CommonViewObject();
        return renderReponse(request, response, vo, "Login");
}

Any suggestion would be appreciated. I need address the issue, thank you!

Upvotes: 4

Views: 1226

Answers (3)

Mani
Mani

Reputation: 3364

Session: wIc4WB62vlaYR_tMRMIc0WpBHchh5fbwpinxgaig4mJRJFhlPUcj!-1795465203!1400921280!1508478820022
Session: wIc4WB62vlaYR_tMRMIc0WpBHchh5fbwpinxgaig4mJRJFhlPUcj!-1795465203!1400921280!1508478820022
Session: wIc4WB62vlaYR_tMRMIc0WpBHchh5fbwpinxgaig4mJRJFhlPUcj!**173379423**!1400921280!1508478820022

Third log line indicates the session being created in different primary jvm / node ( 173379423 ) compare two first two (-795465203).

this may not relate to the session.invalidate calls rather it has problem of creating two session (two different primary node) and expired after time out

I could think of two possible use case

  1. LB is having issues with stickiness. it might got fwd-ed the request to another node which got expired after 60 mins
  2. Primary jvm (node a) may went bad and recover its own , during the window cluster replicated the primary session to new node (node c) , However LB might not noticed the (node a) due to health monitor interval and continued with original primary jvm ( node a)

UPDATE:

  1. Why backup session not trigger session created event? 2. Ideally, is that backup session should timeout with primary session transparently?
  There is no second session being created!!.

Let me try to explain the flow.

  • LB ( F5) receives first request from client.
  • LB routes the traffic to the Node as Round Robin Basis . Picked Node A
  • Node A Generates the session and marked as primary creates Secondary Backup based on its cluster Ranking ( Assume Node B) and pass sessionid as part of Cookies for further communication.

  • Further Requests to LB , LB would check the Cookies and based on Server identifier its routes the traffic to the Node A

  • Node A went Bad / connection issues between Lb to Node A , Now LB cannot route based on Cookie's information , so LB can pick any node based on Round Robin and sends the request to an new Node ( Node D) . At this point Node D pulls session from Secondary based on Cookie information being passed as part request and marked as primary and Node B would remain secondary.

    • Note** , if we have used HttpClusterServlet proxy ( for example apache proxy) and used and (Weblogic Plugin (HttpClusterServlet)) to do load balancing in front your weblogic , then HttpClusterServlet should able to collect your secondary server information ( host and port) and route the traffic to secondary back server. Now Node B would become primary and new secondary would picked based on Node B's cluster ranking.

All session replications should be transparent to the client and there is no second session created in above case.

Note** , in both the cases (LB / Proxy based routing ) the session created in Node A considered as Orphaned , since the session got new primary and secondary . So when users session get invalidate it would invalidate in both current primary and secondary Nodes.

Weblogic documentation provides additional information abt this use case.

Would suggest to track the session based on access log / applications logs to verify when the calls moved to next node. Also make sure LB health monitor request in access logs during the same time period

Would also suggest to make sure the LB configured with Cookie persistent profile.

Upvotes: 0

Hany Sakr
Hany Sakr

Reputation: 2899

I guess you are using the default spring security configuration which by default enables CSRF check, so you may need to disable it and check again

http.csrf().disable()

Upvotes: 0

Ravi
Ravi

Reputation: 31397

If you force the user to logout via the invalidate()method, then HttpSessionListener sessionDestroyed() method is called twice, once when they logout, and a second time after some delayed time period.

This occurs if after the logout you redirect the user back to a web page within your application. What you're essentially doing is starting another session (which may not be immediately obvious if you haven't added security/authentication requirements to all your web pages), and the delayed second call of the sessionDestroyed() method is a timeout occurring.

The simple solution, on logout redirect the user to a web page outside of your application.

You may be interested to look :

JDev/ADF: How to log user login/logout/timeout to the database

JSP Servlet session invalidate() does not make session null

Upvotes: 1

Related Questions