VaadinSession 的会话复制不起作用
Posted
技术标签:
【中文标题】VaadinSession 的会话复制不起作用【英文标题】:Session replication with VaadinSession not working 【发布时间】:2022-01-03 14:08:46 【问题描述】:我们有一个使用 Spring Boot (1.5) 和 Vaadin (7.7) 的 Web 应用程序,并使用 Apache Shiro (1.4.0) 来保证安全性。
应用程序被配置为使用DefaultWebSessionManager
让 Shiro 处理会话管理而不是 servlet 容器。
我们使用的是官方的 Vaadin Spring 集成 (1.2.0),经过一些配置后,一切都按预期工作。 VaadinSession
在内部包含一个包装的 ShiroHttpSession
。
我们希望通过将 Shiro 配置为使用由外部 Cache
支持的 SessionDAO
来实现会话复制,这意味着会话被(反)序列化。
一旦我们开始使用这个SessionDAO
,Vaadin 就会崩溃并停止工作。当为了调试而用内存中的Map
替换外部缓存时,它又可以工作了。
这似乎是由SpringVaadinServlet
引起的,因为它将VaadinSession
存储为会话属性。 VaadinSession
是 Serializable
,Javadoc 显示:
VaadinSession 中的所有内容都应该是可序列化的,以确保 与使用序列化来持久化的方案的兼容性 会话数据。
VaadinSession
内部是一些不是Serializable
的字段,例如Lock
,并且其中封装的 http 会话也被标记为瞬态。
因此,Vaadin 使用的会话一经分发就会被破坏,从而导致大量崩溃。
所以事实证明VaadinSession
不实际上可用于会话复制?为什么会这样?我们该如何解决?
注意:我们还有一个使用 Vaadin 8 的应用程序版本,同样的事情也会发生。看来问题是由 Vaadin Spring 集成引起的。
【问题讨论】:
有一篇关于那个话题的文章:vaadin.com/blog/session-replication-in-the-world-of-vaadin 【参考方案1】:在 VaadinSession 内部是一些不可序列化的字段,例如一个 Lock 并且其中包装的 http 会话也被标记为瞬态。
封装的 http 会话不是 Vaadin 会话的一部分,它是 http 会话。因此它是短暂的。 Lock 也是如此,它的实例存储在 http 会话中。
为了正确实现会话序列化,您需要挂钩序列化事件并在会话反序列化时更新瞬态。 VaadinSession
应该加载VaadinService#loadSession
,它调用VaadinSession#refreshTransients
。
VaadinSession 中的所有内容都应该是可序列化的,以确保与使用序列化来持久化会话数据的方案兼容。
此声明并不意味着您可以开箱即用地序列化您的应用程序。这只是意味着,如果您的应用程序也是可序列化的,那么通过精心设计,您可以序列化整个事物。
例如,出于性能原因,Vaadin 不会在每个可能的情况下更新会话属性。为此有方法VaadinService#storeSession
。因此,您需要覆盖正确的方法或设置请求过滤器。例如。你可以在VaadinService#endRequest
这样做。
请注意,您需要使用粘性会话,以便通过适度的努力使其正常工作。如果您的会话在不同的机器上反序列化,重入锁实例将无效。如果您希望能够在不同的机器上反序列化会话,则需要您的基础设施可以提供分布式锁,您可以使用它而不是 Java 的可重入锁并覆盖 Vaadin 的 getSessionLock
和 setSessionLock
方法使用它。
更多信息的宝贵来源:
来自 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/
【讨论】:
以上是关于VaadinSession 的会话复制不起作用的主要内容,如果未能解决你的问题,请参考以下文章