监控服务器session信息,Tomcat如何监控并删除超时Session详解

favicon_example.ico摘要:

前言偶然发现Tomcat会话时间的半小时,并不是说会话创建后,只有半小时的有效使用时间,而是说会话空闲半小时后,会被删除。索性就翻了一下源码...

前言

偶然发现Tomcat会话时间的半小时,并不是说会话创建后,只有半小时的有效使用时间,而是说会话空闲半小时后,会被删除。索性就翻了一下源码。做了一番整理。

注:空闲时间,指的是同一个会话两次请求之间的间隔时间

Session相关类图

201941683712700.png

httpsession就是大家Servlet层可以直接使用的Session.

Session是Tomcat内部使用的接口,可以做一些内部调用

StandardSession是标准的HttpSession实现,同时它也实现了Session接口,用于Tomcat内部管理

StandardSessionFacade,类名已经指明它就是一个“门面类”,它内部会引用一个StandardSession的对象,但对外只提供HttpSession规定的方法。

Manager相关类图

201941683829946.png

StandardManager与PersitentManager都是Manager的实现,但是它们在存储Session对象的方式上有所不同。

StandarManager

1.Tomcat运行时,把Session存储在内存中

2.Tomcat关闭时(注意是正常的关闭操作,而非突然崩溃),会把Session写入到磁盘中,等到Tomcat重启后再把Session加载进来

PersistentManager

1.总是把Session存储在磁盘中。

Manager与Context的关系

在Tomcat中,一个Context就是部署到Tomcat中的一个应用(Webapp)。每一个Context都有一个单独的Manager对象来管理这个应用的会话信息。

201941683923885.png

Manager如何存储Session

Manager对象会使用一个Map来存储Session对象

Key  => SessionId

Value  => Session Object/**

* The set of currently active Sessions for this Manager, keyed by

* session identifier.

*/

protected Map sessions = new ConcurrentHashMap<>();

当一个请求到达Context的时候,如果它带有JSESSIONID的Cookie,Manager就能依此找到关联的Session对象,放入到Request对象中。

Manager的定期检查

Manager接口有一个backgroundProcess()方法,顾名思义就是后台处理。

/**

* This method will be invoked by the context/container on a periodic

* basis and allows the manager to implement

* a method that executes periodic tasks, such as expiring sessions etc.

*/

public void backgroundProcess();

注:Container接口也有这个方法,这个方法一般在容器启动(start)的时候,开启一个额外的线程来执行这个backgroundProcess方法。其中Context的这个方法启动后,会执行Loader和Manager的backgroundProcess方法。

我们来看看这个方法都做了些什么?

/**

* {@inheritDoc}

*

* Direct call to {@link #processExpires()}

*/

@Override

public void backgroundProcess() {

count = (count + 1) % processExpiresFrequency;

if (count == 0) //如果达到检查频率则开始检查

processExpires();

}

/**

* Invalidate all sessions that have expired.

*/

public void processExpires() {

long timeNow = System.currentTimeMillis();

Session sessions[] = findSessions(); //获取所有session对象

int expireHere = 0 ; //过期session的数量,不要被这个变量名骗了

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

expireHere++;

}

}

long timeEnd = System.currentTimeMillis();

if(log.isDebugEnabled()) //打印记录

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

processingTime += ( timeEnd - timeNow );

}

很多人看到这里,可能会有跟我一样的疑惑,即这里面根本就没有使Session过期失效的操作,好像只做了状态检查。不过后来看到了Session的isValid方法的实现就都明白了。

/**

* Return the isValid flag for this session.

*/

@Override

public boolean isValid() {

if (!this.isValid) {

return false;

}

if (this.expiring) {

return true;

}

if (ACTIVITY_CHECK && accessCount.get() > 0) {

return true;

}

//关键所在

//如果有设置最大空闲时间

//就获取此Session的空闲时间进行判断

//如果已超时,则执行expire操作

if (maxInactiveInterval > 0) {

int timeIdle = (int) (getIdleTimeInternal() / 1000L);

if (timeIdle >= maxInactiveInterval) {

expire(true);

}

}

return this.isValid;

}

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值