Tomcat的Session过期处理策略

简介: Tomcat的Session过期处理策略

tomcat容器实现类都继承了ContainerBase类,容器在启动的时候都会调用ContainerBase类的threadStart()方法,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();  
}  

StandardHost,StandardContext,StandardWrapper类的backgroundProcessorDelay的值都为-1,所以ContainerBackgroundProcessor线程都没有启动.而StandardEngine类在创建的时候 将backgroundProcessorDelay 的值设置为10.所以ContainerBackgroundProcessor线程在StandardEngine里启动,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();//得到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()方法如下:

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()方法,该方法如下:

     

public void backgroundProcess() {  
    count = (count + 1) % processExpiresFrequency;  
    if (count == 0)  
        processExpires();  
}  

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

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过期.过期则清除.

目录
相关文章
|
存储 负载均衡 NoSQL
Tomcat 9.X(9.0.74)集群实现Session共享(基于redisson)
本文主要介绍了tomcat集群环境下基于redis+Redisson实现session共享,分享给大家,供广大从业者学习和参考。
12213 4
|
应用服务中间件 容器
Tomcat设置session超时的几种方式
Tomcat设置session超时的几种方式
425 0
|
负载均衡 NoSQL Java
基于redis 的tomcat session 同步
这里我把Redis放在/XX/下,所以在该目录下执行下列命令: $ wget http://download.redis.io/releases/redis-3.2.1.tar.gz $ tar xzf redis-3.2.1.tar.gz $ cd redis-3.2.1 $ make
152 0
|
负载均衡 Java 应用服务中间件
tomcat集群下的session共享和负载均衡(memcache实现)
tomcat集群下的session共享和负载均衡(memcache实现)
119 0
|
负载均衡 NoSQL Java
tomcat集群下的session共享和负载均衡(redis实现)
tomcat集群下的session共享和负载均衡(redis实现)
256 0
|
NoSQL Java 应用服务中间件
tomcat集群使用redis实现session共享
tomcat集群使用redis实现session共享
276 0
|
存储 负载均衡 NoSQL
tomcat集群环境下如何保证session一致性
tomcat集群环境下如何保证session一致性
238 0
tomcat集群环境下如何保证session一致性
|
NoSQL 应用服务中间件 Redis
tomcat redis session共享的解决方案SessionListener不执行
tomcat redis session共享的解决方案SessionListener不执行
|
NoSQL Java 应用服务中间件
tomcat redis session共享报错 lassNotFoundException: org.apache.commons.pool.impl.GenericObjectPool$Confi
tomcat redis session共享报错 lassNotFoundException: org.apache.commons.pool.impl.GenericObjectPool$Confi
131 0
|
运维 负载均衡 前端开发
Tomcat JVM参数优化策略| 学习笔记
快速学习Tomcat JVM参数优化策略。
Tomcat JVM参数优化策略| 学习笔记