tomcat session管理

最近有空看了一下tomcat 6源码里面对session管理的实现,现在写下来,以供后考,也希望能对对此感兴趣的朋友

有所提示。

 

闲话少说,先贴一下tomcat6的component层次图(此图来自tomcat doc)

  Server                                         就是一个servlet container
           |
         Service                                 包含一个或多个connector的组         
           |
         Engine                                  servlet engine.最顶级的container. 
           |  \ 
           |  --- Cluster --*
           |
         Host                                      第二级container
           |
         ------
        /      \
     Cluster    Context(1-N)             第三级container. servlet context. 也就是一个应用。
        |             \
        |             -- Manager               应用的session管理器
        |                   \
        |                   -- DeltaManager
        |                   -- BackupManager
        |
     ---------------------------
        |                       \
      Channel                    \
    ----------------------------- \
        |                          \
     Interceptor_1 ..               \
        |                            \
     Interceptor_N                    \
    -----------------------------      \
     |          |         |             \
   Receiver    Sender   Membership       \
                                         -- Valve
                                         |      \
                                         |       -- ReplicationValve
                                         |       -- JvmRouteBinderValve 
                                         |
                                         -- LifecycleListener 
                                         |
                                         -- ClusterListener 
                                         |      \
                                         |       -- ClusterSessionListener
                                         |       -- JvmRouteSessionIDBinderListener
                                         |
                                         -- Deployer 
                                                \
                                                 -- FarmWarDeployer
     

OK,基本层级关系说过了,就开始分析session的管理。

1. session 的创建。

   更正:下面这段我理解错了。其实进一步看下来,发现其实session的创建是在每个context里面。具体的创建可以看我

   这篇之后的那篇文章. Session的生成实际是在调用最终处理的servlet的时候生成的。

    session的创建的入口是在Host里面,每次request进来之后,会沿着container 的pipeline一直往下进行、

    处理,顺序是:engine->host->context->wrapper. 而pipeline的作用就是调用对应级别的value对

   request和response进行处理。在StandardHostValue里面首先出现对session的调用:

 

Java代码   收藏代码
  1. public final void invoke(Request request, Response response)  
  2.         throws IOException, ServletException {  
  3.   
  4.         // Select the Context to be used for this Request  
  5.         Context context = request.getContext();  
  6.         if (context == null) {  
  7.             response.sendError  
  8.                 (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,  
  9.                  sm.getString("standardHost.noContext"));  
  10.             return;  
  11.         }  
  12.   
  13.         // Bind the context CL to the current thread  
  14.         if( context.getLoader() != null ) {  
  15.             // Not started - it should check for availability first  
  16.             // This should eventually move to Engine, it's generic.  
  17.             Thread.currentThread().setContextClassLoader  
  18.                     (context.getLoader().getClassLoader());  
  19.         }  
  20.   
  21.         // Ask this Context to process this request  
  22.         context.getPipeline().getFirst().invoke(request, response);  
  23.   
  24.         // Access a session (if present) to update last accessed time, based on a  
  25.         // strict interpretation of the specification  
  26.         if (Globals.STRICT_SERVLET_COMPLIANCE) {  
  27.             request.getSession(false);  
  28.         }  
  29.   
  30.         // Error page processing  
  31.         response.setSuspended(false);  
  32.   
  33.         Throwable t = (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR);  
  34.   
  35.         if (t != null) {  
  36.             throwable(request, response, t);  
  37.         } else {  
  38.             status(request, response);  
  39.         }  
  40.   
  41.         // Restore the context classloader  
  42.         Thread.currentThread().setContextClassLoader  
  43.             (StandardHostValve.class.getClassLoader());  
  44.   
  45.     }  

 

    注意里面的:request.getSession(false) 这一句。这一句最终会调用如下代码;

  

Java代码   收藏代码
  1. protected Session doGetSession(boolean create) {  
  2.   
  3.        // There cannot be a session if no context has been assigned yet  
  4.        if (context == null)  
  5.            return (null);  
  6.   
  7.        // Return the current session if it exists and is valid  
  8.        if ((session != null) && !session.isValid())  
  9.            session = null;  
  10.        if (session != null)  
  11.            return (session);  
  12.   
  13.        // Return the requested session if it exists and is valid  
  14.        Manager manager = null;  
  15.        if (context != null)  
  16.            manager = context.getManager();  
  17.        if (manager == null)  
  18.            return (null);      // Sessions are not supported  
  19.        if (requestedSessionId != null) {  
  20.            try {  
  21.                session = manager.findSession(requestedSessionId);  
  22.            } catch (IOException e) {  
  23.                session = null;  
  24.            }  
  25.            if ((session != null) && !session.isValid())  
  26.                session = null;  
  27.            if (session != null) {  
  28.                session.access();  
  29.                return (session);  
  30.            }  
  31.        }  
  32.   
  33.        // Create a new session if requested and the response is not committed  
  34.        if (!create)  
  35.            return (null);  
  36.        if ((context != null) && (response != null) &&  
  37.            context.getCookies() &&  
  38.            response.getResponse().isCommitted()) {  
  39.            throw new IllegalStateException  
  40.              (sm.getString("coyoteRequest.sessionCreateCommitted"));  
  41.        }  
  42.   
  43.        // Attempt to reuse session id if one was submitted in a cookie  
  44.        // Do not reuse the session id if it is from a URL, to prevent possible  
  45.        // phishing attacks  
  46.        if (connector.getEmptySessionPath()   
  47.                && isRequestedSessionIdFromCookie()) {  
  48.            session = manager.createSession(getRequestedSessionId());  
  49.        } else {  
  50.            session = manager.createSession(null);  
  51.        }  
  52.   
  53.        // Creating a new session cookie based on that session  
  54.        if ((session != null) && (getContext() != null)  
  55.               && getContext().getCookies()) {  
  56.            Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME,  
  57.                                       session.getIdInternal());  
  58.            configureSessionCookie(cookie);  
  59.            response.addCookieInternal(cookie, context.getUseHttpOnly());  
  60.        }  
  61.   
  62.        if (session != null) {  
  63.            session.access();  
  64.            return (session);  
  65.        } else {  
  66.            return (null);  
  67.        }  
  68.   
  69.    }  

   

  通过以上代码,container或者返回一个已存在的session,或者新建一个session,或者返回Null(特殊情况).

      而session的创建是由manager完成的。Manager接口的实现根据具体情况有很多种,比如:

      StandardManager:默认的单机环境tomcat session manager.创建standardsession.

      DeltaSessionManager:适用于集群环境。创建DeltaSession

      ....

     不同的Manager管理不同具体类型的session,从而使得tomcat能够很好的支持集群环境下面的session复制,持久化 等等。比如DeltaSession创建session的时候,会向集群中的其他节点群播一个信息。

   

 

2. session的管理。

    大家都知道tomcat的session需要不断使超时的session失效,那么这个共是怎么实现的呢?

    在StandardContext启动的时候哦,会同时启动一个thread. 这个线程是一个daemon线程,

   会定时调用ManagerBase的一下方法:

  

Java代码   收藏代码
  1. public void processExpires() {  
  2.   
  3.         long timeNow = System.currentTimeMillis();  
  4.         Session sessions[] = findSessions();  
  5.         int expireHere = 0 ;  
  6.           
  7.         if(log.isDebugEnabled())  
  8.             log.debug("Start expire sessions " + getName() + " at " + timeNow + " sessioncount " + sessions.length);  
  9.         for (int i = 0; i < sessions.length; i++) {  
  10.             if (sessions[i]!=null && !sessions[i].isValid()) {  
  11.                 expireHere++;  
  12.             }  
  13.         }  
  14.         long timeEnd = System.currentTimeMillis();  
  15.         if(log.isDebugEnabled())  
  16.              log.debug("End expire sessions " + getName() + " processingTime " + (timeEnd - timeNow) + " expired sessions: " + expireHere);  
  17.         processingTime += ( timeEnd - timeNow );  
  18.   
  19.     }  

 

  很显然,session的有效性管理也通过session具体实现的。比如DeltaSession:

  

Java代码   收藏代码
  1. public void expire(boolean notify, boolean notifyCluster) {  
  2.        if (expiring)  
  3.            return;  
  4.        String expiredId = getIdInternal();  
  5.   
  6.        if(expiredId != null && manager != null &&  
  7.           manager instanceof DeltaManager) {  
  8.            DeltaManager dmanager = (DeltaManager)manager;  
  9.            CatalinaCluster cluster = dmanager.getCluster();  
  10.            ClusterMessage msg = dmanager.requestCompleted(expiredId, true);  
  11.            if (msg != null) {  
  12.                if(dmanager.doDomainReplication()) {  
  13.                    cluster.sendClusterDomain(msg);  
  14.                } else {  
  15.                    cluster.send(msg);  
  16.                }  
  17.            }  
  18.        }  
  19.   
  20.        super.expire(notify);  
  21.   
  22.        if (notifyCluster) {  
  23.            if (log.isDebugEnabled())  
  24.                log.debug(sm.getString("deltaSession.notifying",  
  25.                                       ((ClusterManager)manager).getName(),   
  26.                                       new Boolean(isPrimarySession()),   
  27.                                       expiredId));  
  28.            if ( manager instanceof DeltaManager ) {  
  29.                ( (DeltaManager) manager).sessionExpired(expiredId);  
  30.            }  
  31.        }  
  32.    }  

 

    可以看出,当session失效的时候,manager会广播这个消息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值