使用 VaadinSession 的会话复制不起作用

Session replication with VaadinSession not working

我们有一个 Web 应用程序正在使用 Spring Boot (1.5) 和 Vaadin (7.7),并使用 Apache Shiro (1.4.0) 来确保安全。

应用程序配置为使用 DefaultWebSessionManager 让 Shiro 处理会话管理而不是 servlet 容器。

我们使用的是官方 Vaadin Spring 集成 (1.2.0),经过一些配置后一切正常。 VaadinSession 内部包含一个包装的 ShiroHttpSession

我们希望通过将 Shiro 配置为使用由外部 Cache 支持的 SessionDAO 来实现会话复制,这意味着会话得到(反)序列化。

一旦我们开始使用这个 SessionDAO,Vaadin 就会崩溃并停止工作。当为了调试用内存中的 Map 替换外部缓存时,它再次工作。

这似乎是由 SpringVaadinServlet 引起的,因为它将 VaadinSession 存储为会话属性。 VaadinSessionSerializable 并且 Javadoc 显示:

Everything inside a VaadinSession should be serializable to ensure compatibility with schemes using serialization for persisting the session data.

VaadinSession里面有一些不是Serializable的字段,例如Lock,里面的wrapped http session也被标记为transient。

正因为如此,Vaadin使用的session一分发就断掉,导致大量崩溃。

所以 VaadinSession 不是 在会话复制中实际可用?为什么会这样,我们如何解决这个问题?

注意:我们还有一个使用 Vaadin 8 的应用程序版本,这里发生了同样的事情。看来问题是由 Vaadin Spring 集成引起的。

Inside the VaadinSession are some fields that are not Serializable, for example a Lock and the wrapped http session inside is also marked as transient.

包装的 http 会话不是 Vaadin 会话的一部分,它是 http 会话。因此它是短暂的。 Lock 也是如此,它的实例存储在 http session 中。

为了正确实现会话序列化,您需要挂钩序列化事件并在反序列化会话时更新瞬变。 VaadinSession 应该用 VaadinService#loadSession 加载,它调用 VaadinSession#refreshTransients.

Everything inside a VaadinSession should be serializable to ensure compatibility with schemes using serialization for persisting the session data.

此声明并不意味着您可以开箱即用地序列化您的应用程序。这只是意味着,如果您的应用程序也是可序列化的,那么通过精心设计,您可以序列化整个应用程序。

例如,出于性能原因,Vaadin 不会在每个可能的场合更新会话属性。有方法VaadinService#storeSession。因此,您需要覆盖正确的方法或设置请求过滤器。例如。你可以在 VaadinService#endRequest.

请注意,您需要使用粘性会话,以便通过适度的努力使其正常工作。如果您的会话在不同的机器上被反序列化,则可重入锁实例将无效。如果您希望能够在不同的机器上反序列化会话,则需要您的基础设施可以提供您可以使用的分布式锁,而不是 Java 的可重入锁并覆盖 Vaadin 的 getSessionLocksetSessionLock 方法来使用它。

进一步信息的宝贵来源:

Vaadin 首席技术官的一般说明

https://vaadin.com/blog/session-replication-in-the-world-of-vaadin

开发人员用一个堆栈完成的推荐

https://vaadin.com/learn/tutorials/hazelcast

另一位高级开发人员的想法

https://mvysny.github.io/vaadin-14-session-replication/