为什么在每个会话可能存在并发请求的地方不使用Tomcat的PersistentValve?

时间:2019-01-24 17:06:17

标签: java session tomcat concurrency

PersistentValve顶部的类注释中有一个使用约束:

/**
...
 * <b>USAGE CONSTRAINT</b>: To work correctly it assumes only one request exists
 *                              per session at any one time.
...
 */

为什么在这里有这个约束?仔细阅读代码,我看到三个原因:

  1. 在不同的Tomcat实例上对同一会话的并发请求可能会遭受“最后一次写赢”,因此会话数据可能会丢失。
  2. 由于session.recycle()the shared session object中将管理器设置为null,而另一个请求在attempting to save the session to the store时取消引用管理器,因此对同一Tomcat实例上的同一会话的并发请求可能会导致NPE。 li>
  3. 性能低下(例如,冗余的持久性存储访问等)。

还有其他原因吗?

1 个答案:

答案 0 :(得分:5)

在做SVN-Blame时,我发现此注释是在2008年5月1日的svn修订版652662中添加的,而fixing bug 43343使用的是提交注释:Fix bug 43343. Correctly handle the case where a request arrives for a session we are in the middle of persisting.

该错误的上下文强烈指出了您建议的原因(1),它与数据丢失有关。在最初的错误描述中,OP表示:

  

...我唯一看到其他问题的地方是:   java / org / apache / catalina / valves / PersistentValve.java

     

错误地从PersistentManager获取商店的位置   直接使用它而不是使用管理器API。对我来说这很糟糕   因为经理不能成为经理,而其他逻辑   正在直接访问商店,并且永远不会发生...除非是   仅用于测试用例等。

因此,在此Managers的唯一任务是使用会话Store来存储,加载和删除会话。但是PersistentValve也会这样做,并且很容易干扰管理员的行为。

在提交错误修复程序并修改PersistentManager的过程中,仅将有问题的注释添加到PersistentValve.java中,并删除了未使用的变量:

- StandardHost host = (StandardHost) getContainer();

虽然我不知道此行删除或过去的存在的目的,但我认为提交者Mark Thomas在代码审查和修补程序期间认识到,PersistentValve仅在每个会话最多只有一个活动请求时才能保证一致的会话写入在任何时间点。其他丢失的写操作可能会发生。

我不会判断这有多实用,而只是考虑每个网页展示次数并行加载的大量资源(主要HTML,CSS,JS,图片)。

我仍然不确定使用单个Tomcat实例是否还会造成问题。