我们有一个负载均衡器后面的应用程序,它只支持循环,不支持粘性会话。
Spring应用程序运行在一个OpenShift集群中,部署中有许多吊舱。我们至少有两个吊舱,但可能会放大到10或20,这取决于负载。
应用程序使用Spring会话和Security。Spring会话被配置为使用MongoDB (而不是Redis),因为应用程序已经将MongoDB用于其他目的。
在低到中等负载的功能测试中,我们注意到会话属性“丢失”的问题:更新这些条目的代码成功运行,但是在请求完成后,这些属性的旧内容在会话中。这是随机发生的。
用应用程序的一个实例进行测试,没有进行任何这样的观察。
对我来说,这闻起来像是会话对象写回给Mongo之间的一个竞争条件,在一个荚上有一些HTTP请求,在另一个荚中进行回写,而在“错误的一个”中获胜。
发布于 2020-08-16 12:02:38
我们花了很多时间给DB团队找出这是否与MongoDB客户端连接或服务器配置有关,但经过更深入的研究后,我发现了罪魁祸首:它是session data-mongodb,因为它无法实现增量更新。
https://github.com/spring-projects/spring-session-data-mongodb/issues/106
问题是,没有逻辑可以检查是否需要写入会话存储库,或者是否需要跟踪会话的哪些属性。会话在每个请求结束时被无条件地写回。
如果您有多个并发请求,就像任何正常的web应用程序一样,会话状态会从上次启动并先完成的请求中存活下来。因此,一个简单的图像检索(通过Spring处理程序处理)将导致会话被写回。如果像我们一样,有一个登录处理程序需要大量时间(最多2秒),因为它从后端系统检索了一堆用户信息,那么图像请求将在登录请求之后启动,但在它之前就已经完成了。然后,session data-mongodb决定登录处理程序中的会话状态是陈旧的,并且无法保存它。
因此,在修复该bug之前,我们需要使用不同的存储库,比如Redis。
https://stackoverflow.com/questions/63373650
复制相似问题