【问题标题】:Spring session lazy deserializationSpring session 延迟反序列化
【发布时间】:2018-12-12 17:49:11
【问题描述】:

我有以下情况,我有一个微服务架构,有一个 api 网关和多个下游服务,其中一些有一个独立的会话,这导致我的系统在随机服务调用时抛出过期会话异常。

由于我们无法从头开始重写这些服务,我们从引入 hazelcast 开始,以便所有服务可以共享同一个会话。

现在的问题是,当服务写入其他服务在其类路径中没有的类的对象时,会引发反序列化异常。

为了解决这个问题,我在想,如果只有从服务访问的属性被反序列化,我可能会避免异常,并且一切都应该正常工作。

您知道春季会议是否可以做到这一点,或者可以建议另一种解决方案,让我解决最初的问题?

这是一个重现我的问题的示例项目:https://github.com/deathcoder/hazelcast-shared-session

【问题讨论】:

  • 如果您访问整个会话或会话中的特定值,您应该会看到此问题。是这样吗?
  • 在第二次检查中,似乎 Spring 在每个请求上都通过 id 访问整个会话。
  • 我在插入对象后立即看到反序列化异常,似乎 hazelcast 试图尽快更新,如果有人想尝试的话,明天我可以提供一个示例项目
  • 当然,那真的很有帮助。
  • 使用不同的序列化策略 - 不涉及 Java 序列化的策略(尤其是因为它很慢,体积庞大,而且正如您所学的那样非常脆弱)。例如,序列化为 JSON 并忽略未知属性。最好使用为向后和向前兼容性而设计的真正方案,例如 Avro 或 Protobuf.TL;DR:停止尝试破解简单的解决方案并实际进行一些工程。

标签: java hazelcast spring-session


【解决方案1】:

我相信我知道发生了什么:默认情况下 Spring-Session-Hazelcast 在本地存储会话更新,直到请求完成和请求完成时,在返回响应之前,使用 EntryProcessor 将所有内容发送到集群。 EntryProcessor 要求存储该会话记录的成员上可用的对象类,并且由于数据是分布式的,因此其他一些成员可能存储在另一个实例中创建的会话。根据您的说法,并非所有节点都是相同的,不包含所有类,这会导致序列化异常。

您可以做什么,您可以使用User Code Deployment 功能将那些缺少的类部署到其他成员:https://docs.hazelcast.org/docs/3.11/manual/html-single/index.html#member-user-code-deployment-beta

如果您要更改存储在会话中的对象,您可以将 class-cache-mode 设置为 OFF 以防止不缓存它们而是随每个操作发送。

如果这能解决您的问题,请尝试并告诉我。

【讨论】:

  • 这看起来很有趣,我明天试试
  • 哇——这听起来是一种同时导致可怕的类加载器问题和可怕的性能问题的好方法!你知道每个实例发送类的成本吗?
  • 此解决方案在我的示例中有效,我将其推送到分支上:user-code-deployment
  • @BoristheSpider 是的,你是对的。这就是为什么我说如果您要更改类,那么您可以禁用缓存。似乎 david-buzz 启用了加载类的缓存。
【解决方案2】:

我首先会尽量避免 API 层中的会话。它们的扩展性很差。而且同步会话的可扩展性更差。

尝试改用访问令牌,例如JWT token。令牌应包含足够的用户身份信息以加载处理事务所需的资源(可以缓存资源)。

至于会话中的其他状态——从流程的角度来看,微服务是自包含的,所以所有的中间结果都应该持久化到数据库中。但当然我不知道您的特定应用程序的详细信息,所以这只是一个一般性的想法。

【讨论】:

  • 我同意您的看法,对于较新的服务,我们已经按照您的建议进行操作,但对于旧服务,需要进行大规模的重构才能改变他们使用会话的方式。如果我能找到一个比我们可以慢慢开始重构那些遗留服务的过程更快的解决方案
猜你喜欢
  • 2016-09-09
  • 2013-07-10
  • 2017-02-15
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
  • 2016-11-26
  • 1970-01-01
相关资源
最近更新 更多