您的位置:首页 > 运维架构 > Tomcat

Tomcat的Session过期处理策略

2016-07-20 15:55 537 查看
tomcat容器实现类都继承了ContainerBase类,容器在启动的时候都会调用ContainerBase类的threadStart()方法,threadStart()方法如下:

 

Java代码  


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();  

}  

 StandardHost,StandardContext,StandardWrapper类的backgroundProcessorDelay的值都为-1,所以ContainerBackgroundProcessor线程都没有启动.而StandardEngine类在创建的时候 将backgroundProcessorDelay 的值设置为10.所以ContainerBackgroundProcessor线程在StandardEngine里启动,ContainerBackgroundProcessor线程代码如下:

Java代码  


protected class ContainerBackgroundProcessor implements Runnable {  

  

        public void run() {  

            while (!threadDone) {  

                try {  

                    Thread.sleep(backgroundProcessorDelay * 1000L);  

                } catch (InterruptedException e) {  

                    ;  

                }  

                if (!threadDone) {  

                    Container parent = (Container) getMappingObject();//得到StandardEngine  

                    ClassLoader cl =   

                        Thread.currentThread().getContextClassLoader();  

                    if (parent.getLoader() != null) {  

                        cl = parent.getLoader().getClassLoader();  

                    }  

                    processChildren(parent, cl);  

                }  

            }  

        }  

  

        protected void processChildren(Container container, ClassLoader cl) {  

            try {  

                if (container.getLoader() != null) {  

                    Thread.currentThread().setContextClassLoader  

                        (container.getLoader().getClassLoader());  

                }  

                container.backgroundProcess();  

            } catch (Throwable t) {  

                log.error("Exception invoking periodic operation: ", t);  

            } finally {  

                Thread.currentThread().setContextClassLoader(cl);  

            }  

            Container[] children = container.findChildren();  

            for (int i = 0; i < children.length; i++) {  

                if (children[i].getBackgroundProcessorDelay() <= 0) {  

                    processChildren(children[i], cl);  

                }  

            }  

        }  

  

    }  

 ContainerBackgroundProcessor每隔10秒执行一下线程,线程递归调用StandardEngine,StandardHost,StandardContext,StandardWrapper类的backgroundProcess()方法(backgroundProcess()方法在ContainerBase类中)

backgroundProcess()方法如下:

Java代码  


public void backgroundProcess() {  

      

    if (!started)  

        return;  

  

    if (cluster != null) {  

        try {  

            cluster.backgroundProcess();  

        } catch (Exception e) {  

            log.warn(sm.getString("containerBase.backgroundProcess.cluster", cluster), e);                  

        }  

    }  

    if (loader != null) {  

        try {  

            loader.backgroundProcess();  

        } catch (Exception e) {  

            log.warn(sm.getString("containerBase.backgroundProcess.loader", loader), e);                  

        }  

    }  

    if (manager != null) {//manager的实现类StandardManager  

        try {  

            manager.backgroundProcess();  

        } catch (Exception e) {  

            log.warn(sm.getString("containerBase.backgroundProcess.manager", manager), e);                  

        }  

    }  

    if (realm != null) {  

        try {  

            realm.backgroundProcess();  

        } catch (Exception e) {  

            log.warn(sm.getString("containerBase.backgroundProcess.realm", realm), e);                  

        }  

    }  

    Valve current = pipeline.getFirst();  

    while (current != null) {  

        try {  

            current.backgroundProcess();  

        } catch (Exception e) {  

            log.warn(sm.getString("containerBase.backgroundProcess.valve", current), e);                  

        }  

        current = current.getNext();  

    }  

    lifecycle.fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);  

}  

 

   在调用StandContext类的backgroundProcess()方法时, 会调用StandardManager的backgroundProcess()方法,该方法如下:

       

Java代码  


public void backgroundProcess() {  

    count = (count + 1) % processExpiresFrequency;  

    if (count == 0)  

        processExpires();  

}  

 

 processExpiresFrequency的默认值为6,所以每6*10秒会调一次processExpires()方法,processExpires()方法如下:

  

Java代码  


public void processExpires() {  

  

    long timeNow = System.currentTimeMillis();  

    Session sessions[] = findSessions();  

    int expireHere = 0 ;  

      

    if(log.isDebugEnabled())  

        log.debug("Start expire sessions " + getName() + " at " + timeNow + " sessioncount " + sessions.length);  

    for (int i = 0; i < sessions.length; i++) {  

        if (sessions[i]!=null && !sessions[i].isValid()) {//判断session是否有效,无效则清除  

            expireHere++;  

        }  

    }  

    long timeEnd = System.currentTimeMillis();  

    if(log.isDebugEnabled())  

         log.debug("End expire sessions " + getName() + " processingTime " + (timeEnd - timeNow) + " expired sessions: " + expireHere);  

    processingTime += ( timeEnd - timeNow );  

  

}  

  该方法主要判断session是否过期,过期则清除.

 

  

    整个过程看起来有点复杂,简单地来说,就是tomcat服务器在启动的时候初始化了一个守护线程,定期6*10秒去检查有没有Session过期.过期则清除.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: