如何让主会话与Weblogic上的辅助会话共享“会话超时”?

时间:2017-10-20 08:20:58

标签: java session java-ee weblogic weblogic12c

更新问题描述以更加明确和详细。

我有 weblogic 12c ,配置了一个群集,群集中有4个节点实例,默认加载算法是循环,复制类型是 MAN < / strong>即可。我在所有4个节点上部署了一个Web应用程序。

我第一次设计的是:

一旦用户会话失效,就执行注销相关的业务逻辑。 将逻辑代码放在SessionListener.java的“sessionDestroyed”方法中,该方法实现HttpSession接口。 如您所知,会话失效可能由2个案例引起,一个是手动注销,另一个是J2ee容器触发超时。我的问题是因为第二种情况而发生的。

问题:

“SessionDestroyed”事件中的业务逻辑代码对于一个用户超时执行两次,这是不期望的并且导致业务错误。我发现节点A上的Primary Http Session和节点B上的Backup Session都触发了weblogic“SessionDestroyed”事件。

问题:

  1. 为什么节点B上的备份会话会触发会话超时事件 虽然节点A上的主会话已经超时 ?
  2. 如何让备份会话知道主会话 已经失效?
  3. 附加日志,你可以看到第一行和第二行是主会话,第三行是备份会话,可以通过行尾中的会话ID来证明。

    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
    

    以下是我的weblogic配置:

    <?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>
    

    这是我在Web应用程序内的web.xml中配置的会话:

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

    这是我的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()));
            }
        }
    }
    

    此代码用于手动注销:

    @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");
    }
    

    任何建议都将不胜感激。我需要解决这个问题,谢谢!

3 个答案:

答案 0 :(得分:1)

如果强制用户通过invalidate()方法注销,则HttpSessionListener sessionDestroyed()方法会在注销时调用两次,在一段延迟时间后第二次调用。

如果在注销后您将用户重定向回应用程序中的网页,则会发生 。您实际上正在做的是开始另一个会话 (如果您没有向所有网页添加安全/身份验证要求,这可能不会立即显现),以及 sessionDestroyed()方法的第二次延迟调用是超时发生。

简单的解决方案,在注销时将用户重定向到应用程序之外的网页。

您可能有兴趣看一下:

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

JSP Servlet session invalidate() does not make session null

答案 1 :(得分:0)

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

第三个日志行表示在不同的主jvm /节点( 173379423 )中创建的会话比较前两个( -795465203 )。

这可能与session.invalidate调用无关,而是存在创建两个会话(两个不同的主节点)并在超时后过期的问题

我可以想到两个可能的用例

  1. LB有粘性问题。它可能会将请求转发给另一个在60分钟后过期的节点
  2. 在窗口集群将主会话复制到新节点(节点c)期间,主jvm(节点a)可能变坏并自行恢复,但LB可能由于运行状况监视器间隔而未注意到(节点a)并继续与原始主要jvm(节点a)
  3. 更新:

      
        
    1. 为什么备份会话不会触发会话创建的事件? 2.理想情况下,备份会话是否应该与主会话超时   透明?
    2.   
      There is no second session being created!!.
    

    让我试着解释一下这个流程。

    • LB(F5)收到客户的第一个请求。
    • LB将流量路由到Round Robin Basis。挑选节点A
    • 节点A生成会话并标记为主要会根据其群集排名(假设节点B)创建辅助备份,并将会话ID作为Cookie的一部分传递以进行进一步通信。

    • 对LB,LB的进一步请求将检查Cookies并根据服务器标识符将其路由到节点A的流量

    • 节点A在Lb与节点A之间出现错误/连接问题,现在LB无法根据Cookie的信息进行路由,因此LB可以根据循环选择任意节点并将请求发送到新节点(节点D)。此时,节点D根据作为部分请求传递的Cookie信息从辅助节点拉取会话,并标记为主节点,节点B将保持为次要节点。

      • 注意**,如果我们使用HttpClusterServlet代理(例如apache代理)并使用和(Weblogic插件(HttpClusterServlet))在weblogic前面进行负载均衡,那么{{1应该能够收集您的辅助服务器信息(主机和端口)并将流量路由到辅助后台服务器。现在节点B将成为主要节点,并且将根据节点B的集群排名选择新的辅助节点。

    所有会话复制对客户端都应该是透明的,并且在上述情况下没有创建第二个会话。

    注意**,在两种情况下(基于LB /代理的路由),在节点A中创建的会话被视为孤立,因为会话获得了新的主要和次要。因此,当用户会话无效时,它将在当前主节点和辅助节点中失效。

    Weblogic documentation提供了此用例的其他信息。

    建议根据访问日志/应用程序日志跟踪会话,以验证调用何时移至下一个节点。还要确保在同一时间段内访问日志中的LB运行状况监视器请求

    还建议确保LB配置了Cookie持久性配置文件。

答案 2 :(得分:0)

我猜您使用默认的spring安全配置,默认启用CSRF检查,因此您可能需要禁用它并再次检查

http.csrf().disable()