转载

Tomcat 的 Session 持久化策略

关于Tomcat的Session,我们都知道默认是保存在内存中。为了解决重启应用服务器Session丢失的问题,Tomcat内部的StandardManager会在正常的关闭时钝化活动的Session 并在重启的时候重新加载。

而Tomcat在 StandardManager 之外,还提供了对应持久化Session的Manager实现:  PersistentManager ,目前对应的有两种持久化的实现

  • FileStore

  • JDBCStore

分别是将活动的Session保存在磁盘上和保存到数据库中。

本次我们以FileStore为例,来分析下PersistentManager在Tomcat中的实现。

配置

PersistentManager的配置基本上是这样的:

<Manager className="org.apache.catalina.session. PersistentManager " debug="0" saveOnRestart="true" maxActiveSessions="-1" minIdleSwap="-1" maxIdleSwap="5" maxIdleBackup="3" >

< Store className="org.apache.catalina.session.FileStore" directory="/home/mytestsession"/>

</Manager>

对于FileStore和JDBCStore,基本配置都类似,有差异的只是 Store 中对应的具体属性,比如JDBCStore需要额外指定数据的用户名和密码等。上面的配置可以直接 用于FileStore。

其中,像 maxIdleBackupmaxIdleSwapminIdleSwap 默认都是关闭的,默认值都是-1。当然,我们上面的配置是修改过的。默认的行为会和StandardManager一致,即在关闭重启时进行Session的钝化和解析。

而当按照我们上面的配置启动Tomcat后,服务器会根据maxIdleBackup的时间,以秒为单位,进行空闲Session的持久化。在配置的目录中,会生成以sessionId为文件名.session的文件

例如:5E62468BFF33CF7DE28464A76416B85E.session

主要参数说明:

  • saveOnRestart -当服务器关闭时,是否要将所有的session持久化;

  • maxActiveSessions - 可处于活动状态的session数;

  • minIdleSwap/maxIdleSwap -session处于不活动状态最短/长时间(s),sesson对象转移到File Store中;

  • maxIdleBackup -大于这一时间时,会将session备份。

写文件:

public void save(Session session) throws IOException {

// Open an output stream to the specified pathname, if any

File file = file(session.getIdInternal());

if (file == null) {

return;

}

if (manager.getContext().getLogger().isDebugEnabled()) {

manager.getContext().getLogger().debug(sm.getString(getStoreName() + ".saving",

session.getIdInternal(), file.getAbsolutePath()));

}

try (FileOutputStream fos = new FileOutputStream(file.getAbsolutePath());

ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(fos))) {

((StandardSession)session). writeObjectData (oos);

}

}

我们来看load操作,和StandardManager加载Session基本一致,先创建空的session,再readObjectData:

public Session load(String id) {

File file = file(id);

Context context = getManager().getContext();

try (FileInputStream fis = new FileInputStream(file.getAbsolutePath());

ObjectInputStream ois = getObjectInputStream(fis)) {

StandardSession session = (StandardSession) manager.createEmptySession();

session.readObjectData(ois);

session.setManager(manager);

return session;

} catch (FileNotFoundException e) {

return null;

}

}

删除操作:

public void remove(String id) throws IOException {

File file = file(id);

file.delete();

}

而这些load,remove等操作的触发点,就是我们之前提到过的 后台线程 :我们在前面分析过期的session是如何处理的时候,曾提到过,可以移步这里: 对于过期的session,Tomcat做了什么?

都是使用 backgroundProcess

public void backgroundProcess() {

count = (count + 1) % processExpiresFrequency;

if (count == 0)

processExpires();

}

PersistentManager 的processExpires方法中,重点有以下几行

processPersistenceChecks();

if (getStore() instanceof StoreBase) {

((StoreBase) getStore()).processExpires();

}

其中在 processPersistenceChecks 中,就会对我们上面配置的几项进行检查,判断是否要进行session文件的持久化等操作

/**

* Called by the background thread after active sessions have been checked

* for expiration, to allow sessions to be swapped out, backed up, etc.

* /

public void processPersistenceChecks() {

processMaxIdleSwaps();

processMaxActiveSwaps();

processMaxIdleBackups();

}

此外,通过配置 pathname 为空,即可禁用session的持久化策略,在代码中,判断pathname为空时,不再创建持久化文件,从而禁用此功能。

<Manager pathname="" />

总结下,正如文档中所描述,StandardManager所支持的重启时加载已持久化的Session这一特性,相比PersistentManager只能算简单实现。要实现更健壮、更符合生产环境的重启持久化,最好使用PersistentManager并进行恰当的配置。

关于Session,你可能还想了解这些:

详解集群内Session高可用的实现原理

深入Tomcat源码分析Session到底是个啥!

禁用Cookie后,Session怎么样使用?

扫描或长按下方二维码,共同成长!

Tomcat 的 Session 持久化策略

原文  http://mp.weixin.qq.com/s?__biz=MzI3MTEwODc5Ng==&mid=2650859204&idx=1&sn=5ca2f23c991309cc66e05a99a4cbb63d
正文到此结束
Loading...