`
toking79
  • 浏览: 22675 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Tomcat源码系列6--Tomcat的Session生成和管理2

阅读更多

下面谈一谈Session的管理。


一. Session的管理 
当tomcat启动时,会开启一个后台线程,这个后台线程是随容器的启动而启动的,它将定期检查会话超时。
(org.apache.catalina.core.ContainerBase.threadStart()) 

protected void threadStart() { 

        if (thread != null) 
            return; 
// 
        if (backgroundProcessorDelay <= 0) 
            return; 

        threadDone = false; 
        String threadName = "ContainerBackgroundProcessor[" + toString() + "]"; 
        thread = new Thread(new ContainerBackgroundProcessor(), threadName); 
        thread.setDaemon(true); 
        thread.start(); 
    }

 

1.此时会新建一个ContainerBackgroundProcessor线程。
(org.apache.catalina.core.ContainerBase.ContainerBackgroundProcessor) 

protected class ContainerBackgroundProcessor implements Runnable { 

        public void run() { 
            while (!threadDone) { 
                try { 
                    Thread.sleep(backgroundProcessorDelay * 1000L); 
                } catch (InterruptedException e) { 
                    ; 
                } 
                if (!threadDone) { 
                    Container parent = (Container) getMappingObject(); 
                    ClassLoader cl = 
                        Thread.currentThread().getContextClassLoader(); 
                    if (parent.getLoader() != null) { 
                        cl = parent.getLoader().getClassLoader(); 
                    } 
                    processChildren(parent, cl);//parent为StandardEngine                
} 
            } 
        }

 

2.processChildren(parent,cl)--->processChildren(StandardHost,cl) --->processChildren(StandardContext,cl),最后StandardContext#backgroundProcess()方法被调用。 

(org.apache.catalina.core.StandardContext.backgroundProcess()) 
    public void backgroundProcess() { 
        if (!started) 
            return; 
        count = (count + 1) % managerChecksFrequency; 

        if ((getManager() != null) && (count == 0)) { 
            try { 
                getManager().backgroundProcess(); 
            } catch ( Exception x ) { 
                log.warn("Unable to perform background process on manager",x); 
      } 
  }

 


3. StandardManager#processExpires()方法被调用。
org.apache.catalina.session.StandardManager.backgroundProcess() 

public void backgroundProcess() { 
        processExpires(); 
    }

 

4. StandardManager#processExpires()被调用,通过调用session#isValid()方法判断session是否有效,如果session无效将被销毁。
(org.apache.catalina.session.StandardManager.processExpires())
/**
     * 处理所有已失效的session
     */ 
 

   public void processExpires() { 

        long timeNow = System.currentTimeMillis(); 
        Session sessions[] = findSessions(); 

        for (int i = 0; i < sessions.length; i++) { 
            StandardSession session = (StandardSession) sessions[i]; 
            if (!session.isValid()) { 
                expiredSessions++; 
            } 
        } 
        long timeEnd = System.currentTimeMillis(); 
        processingTime += ( timeEnd - timeNow ); 

    }

 

5.StandardSession#isValid()最终调用expire(true),然后返回isValid()的布尔值。
(org.apache.catalina.session.StandardSession.isValid()) 

public boolean isValid() { 

        if (this.expiring) { 
            return true; 
        } 
        if (!this.isValid ) { 
            return false; 
        } 
        if (accessCount > 0) { 
            return true; 
        } 
        if (maxInactiveInterval >= 0) { 
            long timeNow = System.currentTimeMillis(); 
            int timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L); 
            if (timeIdle >= maxInactiveInterval) { 
                expire(true);※3 
            } 
        } 

        return (this.isValid); 
    }

 
※3
StandardSession.expire()方法被调用,session被销毁。
(org.apache.catalina.session.StandardSession.expire(boolean notify))

public void expire(boolean notify) { 
       
        if (expiring) 
            return; 
        synchronized (this) { 

            if (manager == null) 
                return; 

            expiring = true; 
        
            //唤醒相关的应用程序事件监听者 
            Context context = (Context) manager.getContainer(); 
            Object listeners[] = context.getApplicationLifecycleListeners(); 
            if (notify && (listeners != null)) { 
                HttpSessionEvent event = 
                    new HttpSessionEvent(getSession()); 
                for (int i = 0; i < listeners.length; i++) { 
                    int j = (listeners.length - 1) - i; 
                    if (!(listeners[j] instanceof HttpSessionListener)) 
                        continue; 
                    HttpSessionListener listener = 
                        (HttpSessionListener) listeners[j]; 
                    try { 
                        fireContainerEvent(context, 
                                           "beforeSessionDestroyed", 
                                           listener); 
                        listener.sessionDestroyed(event); 
                        fireContainerEvent(context, 
                                           "afterSessionDestroyed", 
                                           listener); 
                    } catch (Throwable t) { 
                        try { 
                            fireContainerEvent(context, 
                                               "afterSessionDestroyed", 
                                               listener); 
                        } catch (Exception e) { 
                            ; 
                        } 
                        manager.getContainer().getLogger().error 
                            (sm.getString("standardSession.sessionEvent"), t); 
                    } 
                } 
            } 
            accessCount = 0; 
            setValid(false); 

            // Remove this session from our manager's active sessions 
            if (manager != null) 
                manager.remove(this); 

            //唤醒相关的session事件监听者 
            if (notify) { 
                fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null); 
            } 

            // 处理完毕后,设置expiring为false 
            expiring = false; 

            //解除任何与此相关的session对象的绑定 

            String keys[] = keys(); 
            for (int i = 0; i < keys.length; i++) 
                removeAttributeInternal(keys[i], notify); 
} 
} 

 

 

1
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics