Tomcat的Session过期处理策略

tomcat容器实现类都继承了ContainerBase类,容器在启动的时候都会调用ContainerBase类的threadStart()方法,threadStart()方法如下:

 

Java代码   收藏代码
  1. protected void threadStart() {  
  2.   
  3.     if (thread != null)  
  4.         return;  
  5.     if (backgroundProcessorDelay <= 0)  
  6.         return;  
  7.   
  8.     threadDone = false;  
  9.     String threadName = "ContainerBackgroundProcessor[" + toString() + "]";  
  10.     thread = new Thread(new ContainerBackgroundProcessor(), threadName);  
  11.     thread.setDaemon(true);  
  12.     thread.start();  
  13. }  

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

Java代码   收藏代码
  1. protected class ContainerBackgroundProcessor implements Runnable {  
  2.   
  3.         public void run() {  
  4.             while (!threadDone) {  
  5.                 try {  
  6.                     Thread.sleep(backgroundProcessorDelay * 1000L);  
  7.                 } catch (InterruptedException e) {  
  8.                     ;  
  9.                 }  
  10.                 if (!threadDone) {  
  11.                     Container parent = (Container) getMappingObject();//得到StandardEngine  
  12.                     ClassLoader cl =   
  13.                         Thread.currentThread().getContextClassLoader();  
  14.                     if (parent.getLoader() != null) {  
  15.                         cl = parent.getLoader().getClassLoader();  
  16.                     }  
  17.                     processChildren(parent, cl);  
  18.                 }  
  19.             }  
  20.         }  
  21.   
  22.         protected void processChildren(Container container, ClassLoader cl) {  
  23.             try {  
  24.                 if (container.getLoader() != null) {  
  25.                     Thread.currentThread().setContextClassLoader  
  26.                         (container.getLoader().getClassLoader());  
  27.                 }  
  28.                 container.backgroundProcess();  
  29.             } catch (Throwable t) {  
  30.                 log.error("Exception invoking periodic operation: ", t);  
  31.             } finally {  
  32.                 Thread.currentThread().setContextClassLoader(cl);  
  33.             }  
  34.             Container[] children = container.findChildren();  
  35.             for (int i = 0; i < children.length; i++) {  
  36.                 if (children[i].getBackgroundProcessorDelay() <= 0) {  
  37.                     processChildren(children[i], cl);  
  38.                 }  
  39.             }  
  40.         }  
  41.   
  42.     }  

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

backgroundProcess()方法如下:

Java代码   收藏代码
  1. public void backgroundProcess() {  
  2.       
  3.     if (!started)  
  4.         return;  
  5.   
  6.     if (cluster != null) {  
  7.         try {  
  8.             cluster.backgroundProcess();  
  9.         } catch (Exception e) {  
  10.             log.warn(sm.getString("containerBase.backgroundProcess.cluster", cluster), e);                  
  11.         }  
  12.     }  
  13.     if (loader != null) {  
  14.         try {  
  15.             loader.backgroundProcess();  
  16.         } catch (Exception e) {  
  17.             log.warn(sm.getString("containerBase.backgroundProcess.loader", loader), e);                  
  18.         }  
  19.     }  
  20.     if (manager != null) {//manager的实现类StandardManager  
  21.         try {  
  22.             manager.backgroundProcess();  
  23.         } catch (Exception e) {  
  24.             log.warn(sm.getString("containerBase.backgroundProcess.manager", manager), e);                  
  25.         }  
  26.     }  
  27.     if (realm != null) {  
  28.         try {  
  29.             realm.backgroundProcess();  
  30.         } catch (Exception e) {  
  31.             log.warn(sm.getString("containerBase.backgroundProcess.realm", realm), e);                  
  32.         }  
  33.     }  
  34.     Valve current = pipeline.getFirst();  
  35.     while (current != null) {  
  36.         try {  
  37.             current.backgroundProcess();  
  38.         } catch (Exception e) {  
  39.             log.warn(sm.getString("containerBase.backgroundProcess.valve", current), e);                  
  40.         }  
  41.         current = current.getNext();  
  42.     }  
  43.     lifecycle.fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);  
  44. }  

 

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

       

Java代码   收藏代码
  1. public void backgroundProcess() {  
  2.     count = (count + 1) % processExpiresFrequency;  
  3.     if (count == 0)  
  4.         processExpires();  
  5. }  

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

  

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()) {//判断session是否有效,无效则清除  
  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是否过期,过期则清除.

 

  

    整个过程看起来有点复杂,简单地来说,就是tomcat服务器在启动的时候初始化了一个守护线程,定期6*10秒去检查有没有Session过期.过期则清除.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值