当前位置: 首页 > 知识库问答 >
问题:

为什么Tomcat8没有在创建后立即将会话持久化到datastore?

申屠锦
2023-03-14

有一些不寻常的行为我不明白。当我登录到我的网站时,将创建一个新的会话。登录后,我可以立即向web服务器发送请求并执行一些事情,所有这些都需要一个有效的会话(我已经有了)。

问题是,在我登录之后,新的会话条目不会立即持久化到datastore(DynamoDB)。事实上,每次创建一个新会话时,我发现会话条目出现在Dynamodb中需要30秒到1分钟,有时甚至更长时间。

现在,我之所以能够在登录后立即发出需要身份验证的请求,显然是因为单个Tomcat实例以某种方式缓存会话数据,然后可能会在空闲时将会话持久化到datastore。

从上次访问会话到有资格将会话保存到会话存储区的时间间隔(以秒为单位)...

我不介意会话数据不被立即更新(像上次访问时间),如果事实上我不介意增加到1或2分钟。但是在创建时立即持久化会话似乎是Tomcat没有提供的一个关键功能。

最后,我还应该提到,我已经浏览了我使用的会话管理器库的所有源代码(对于DynamoDB的持久性,它只是几个类),它基本上只处理从Tomcat会话到DynamoDB项的转换过程,反之亦然,加上过期的会话收获等。因此,在我看来,这就像是Tomcat的问题,除非我误解了什么。

实际上,我已经设法找到了一个解决新会话不能立即持久化到数据库中的问题的方法。我会加上一个详细的答案,这样这个问题就不会变成一个怪物。

共有1个答案

融建树
2023-03-14

这是一个我正在使用的解决方案,它为我解决了这个问题。我想这可以被认为是一个黑客,但它是有效的,我没有看到任何问题做它(但如果有人有问题,请让我知道)。

基本上,我只是在创建会话后强制保存它。问题实际上是找到一种方法来获取对会话管理器数据存储的引用,因为servlet API不公开对它的访问。因此,首先我必须使用反射获得对会话管理器的引用:

private static PersistentManagerBase getSessionManager(HttpSession session) {
    StandardSession stdSession;
    try {
        Field facadeSessionField = StandardSessionFacade.class.getDeclaredField("session");
        facadeSessionField.setAccessible(true);
        stdSession = (StandardSession) facadeSessionField.get(session);

    } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
        System.out.println("Error attempting to retrieve session manager => " 
                + e.getMessage() + " -- the new session has been created anyway, just not immediately persisted to the database");
        e.printStackTrace();
        return null;
    }
    return (PersistentManagerBase) stdSession.getManager();
}

...然后我可以获得对store对象的引用。

Store store = manager.getStore();
private static Session createStandardSession(HttpSession newSession, Manager manager) {
    StandardSession stdSession = new StandardSession(manager);
    stdSession.setId(newSession.getId());
    stdSession.setCreationTime(newSession.getCreationTime());
    stdSession.setValid(true);
    stdSession.setMaxInactiveInterval(newSession.getMaxInactiveInterval());
    Enumeration<String> attrNames = newSession.getAttributeNames();
    while ( attrNames.hasMoreElements() ){
        String attrName = attrNames.nextElement();
        stdSession.setAttribute(attrName, newSession.getAttribute(attrName));
    }
    return stdSession;
}
HttpSession newSession = request.getSession(true);
PersistentManagerBase manager = getSessionManager(newSession);
if (manager != null) {
    manager.getStore().save( createStandardSession(newSession, manager) );
}
    null
 类似资料:
  • 问题内容: 我曾经用PHP启动会话,但是当我的浏览器关闭时,该会话消失了。 如何使用PHP创建持续持续浏览器关闭的持久会话? 问题答案: 请参阅值session.cookie_lifetime。 默认值意味着在浏览器关闭时结束会话。 您可以使用ini_set在开始会话之前直接在应用程序中覆盖此值或在应用程序中设置它。将其设置为大于此值将导致会话在该持续时间内存活。 例如 上面的示例使会话cooki

  • 来自ZooKeeper服务器的日志:

  • 问题内容: 我有一个托管bean,其中包含当前页面的实体对象列表。在我创建一个新对象并在事务中使用persist()将其持久保存到数据库之后;在另一个事务中,当我调用merge时(由于该实体由于先前的事务提交而处于分离状态);实体管理器无法在持久性上下文中找到对象,并向数据库抛出选择查询。我是否缺少某些东西,或者是正常行为? 更新:当我使用mysql数据库和自动生成的ID列时,存在上述问题。当我在

  • 问题内容: 经过反复试验,我将问题缩小到下面的第5行。由于某种原因,.js响应将结束用户会话。使用3.0.4并设计1.1.7(和jQuery 1.5)。 此外,@ organization正在更新,并且日志中将显示Completed 200 OK,因此用户不知道他/她已注销,直到尝试下一个操作为止。 任何帮助和指导,我们将不胜感激。 和 问题答案: 非常感谢Google Devise Group的

  • 本文向大家介绍RabbitMQ 持久化有什么缺点?相关面试题,主要包含被问及RabbitMQ 持久化有什么缺点?时的应答技巧和注意事项,需要的朋友参考一下 持久化的缺地就是降低了服务器的吞吐量,因为使用的是磁盘而非内存存储,从而降低了吞吐量。可尽量使用 ssd 硬盘来缓解吞吐量的问题。