【问题标题】:Spring Session with MongoDB: race condition?与 MongoDB 的春季会议:竞争条件?
【发布时间】:2020-08-12 09:27:30
【问题描述】:

我们在负载均衡器后面有一个应用程序,它只支持循环,没有粘性会话。

Spring Boot 应用程序在 OpenShift 集群中运行,部署中有许多 pod。我们至少有两个 pod,但可能会根据负载将其扩展到 10 或 20 个。

应用程序使用 Spring Session 和 Spring Security。 Spring Session 被配置为使用 MongoDB(而不是 Redis),因为应用程序已经将 MongoDB 用于其他目的。

在低到中等负载的功能测试期间,我们注意到会话属性“丢失”的问题:更新这些条目的代码运行成功,但在请求完成后,属性的旧内容在会话中.这是随机发生的。

使用应用程序的单个实例进行测试,没有进行此类观察。

对我来说,这听起来像是会话对象回写到 Mongo 之间的竞争条件,一个 pod 上的一些 HTTP 请求与另一个 pod 中的回写竞争,而“错误的”获胜。

  • 这是 Spring Session with MongoDB 的有效使用场景吗?换句话说,这应该有效吗?
  • 如果它应该工作,我怎样才能知道发生了什么,我可以做些什么来解决这个问题?
  • 如果它不应该工作,是否有一个 Spring Session 设置允许跨应用程序服务器共享会话状态而没有竞争条件?

【问题讨论】:

  • 这可能与读/写仲裁有关吗?复制中有一些延迟?我们所说的 MongoDB 是什么? MongoDB应该可以很好地托管会话,尽管 replset 或 clusters 可能不是最好的用例 - 那么,redis 确实是一个很好的选择,可以很容易地部署在 OpenShift 中

标签: java mongodb spring-boot spring-session


【解决方案1】:

我们花了很多时间与 DB 团队一起试图弄清楚这是否与 MongoDB 客户端连接或服务器配置有关,但经过更深入的研究,我找到了罪魁祸首:它是 spring-session -data-mongodb,因为它无法实现增量更新。

https://github.com/spring-projects/spring-session-data-mongodb/issues/106

问题是没有逻辑来检查是否需要写入会话存储库,或者任何跟踪会话的哪些属性已更改。会话在每个请求结束时无条件地写回。

如果您有多个并发请求,就像任何普通的 Web 应用程序一样,会话状态会从最后启动并首先完成的请求中继续存在。因此,一个简单的图像检索(通过 Spring 处理程序处理)将导致会话被写回。如果你像我们一样有一个登录处理程序,它需要大量时间(最多 2 秒),因为它从后端系统检索一堆用户信息,对图像的请求将在登录请求之后开始,但会在它之前完成。 spring-session-data-mongodb 然后确定来自登录处理程序的会话状态是陈旧的,并且无法保存它。

因此,在修复该错误之前,我们将需要使用不同的存储库,例如 Redis。

【讨论】:

    猜你喜欢
    • 2013-03-30
    • 2019-03-21
    • 1970-01-01
    • 2018-11-30
    • 2015-04-11
    • 2011-12-31
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多