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

dch*_*les 6 java concurrency session tomcat

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

/**
...
 * <b>USAGE CONSTRAINT</b>: To work correctly it assumes only one request exists
 *                              per session at any one time.
...
 */
Run Code Online (Sandbox Code Playgroud)

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

  1. 在不同的Tomcat实例上对同一会话的并发请求可能会受到"最后写入获胜"的影响,从而可能会丢失会话数据.
  2. 由于session.recycle()共享会话对象中将管理器设置为null而在尝试将会话保存到存储时另一个请求解除引用管理器,因此在同一Tomcat实例上对同一会话的并发请求可能会导致NPE .
  3. 性能低效(例如,冗余持久性存储访问等).

还有其他原因吗?

Sel*_*ron 6

做SVN-Blame我发现这个评论是在2008年5月1日的svn修订版652662中添加的,同时使用提交注释修复bug 43343:修复bug 43343.正确处理请求到达会话的情况我们正处于持续存在的状态..

该错误的上下文强烈指出您的建议原因(1)它是关于数据丢失.在最初的错误描述中,OP说:

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

它从PersistentManager错误地抓取商店并直接使用它而不是使用管理器API.对我而言,这是不好的,因为经理不能成为经理而这个其他逻辑直接访问商店并且永远不会发生...除非它仅用于测试用例等.

所以在这里它被认为是Managers使用会话Store来存储,加载和删除会话的唯一任务.但这也是PersistentValve一样的,可能很容易干扰经理的工作.

在修改提交的错误修复提交期间PersistentManager,仅添加了有问题的注释PersistentValve.java以及删除了未使用的变量:

- StandardHost host = (StandardHost) getContainer();
Run Code Online (Sandbox Code Playgroud)

虽然我不知道这行删除或过去存在的目的,但我认为提交者Mark Thomas在代码审查和补丁中认识到PersistentValve只能保证在任何时候每个会话最多只有一个请求活动时会话会话写入及时.否则丢失的写入可能会发生.

我不会判断这是多么实用,但只考虑每个网页印象(主HTML,CSS,JS,图像)并行加载的大量资源.

我仍然不确定使用单个Tomcat实例是否会出现问题.