我看到了一个以这种方式实现内存会话的Web框架。会话对象被添加到Cache with timeout。当时间结束时,会话将自动从缓存中删除。为了保护竞争条件,每个请求都应获取对给定会话对象的锁定以继续。每个请求都会 “触摸” 缓存中的会话以刷新超时。
一切都很好,直到发现这种情况。比如说,一次操作需要很长时间,比超时时间长。另一个请求来到并等待会话锁定,该锁定当前由长时间请求保持。最后,长时间请求结束,它释放锁定。但是,由于它已经比超时花费更长的时间,因此会话对象已从Cache中删除。这是显而易见的,因为持有锁的唯一请求没有机会“ 触摸 ”缓存中的会话对象。第二个请求获取锁定但无法检索过期的Session对象。糟糕...
要解决此问题,第二个请求必须重新创建Session对象。但是,这就像从坟墓中挖出一具埋藏的尸体,并试图让它恢复生机。它会导致错误的代码。
我想知道在会话中实现超时的最佳方法是什么来处理这种情况。我知道当前平台必须具有良好的会话机制。我只想知道引擎盖下的情况。
答案 0 :(得分:2)
Hi Morgan Cheng(香港人?),
当您的长时间请求完成时, touch
- 会话对象可以解决您的问题吗?
让我们通过一个例子来讨论解决方案。当请求到达时,您触摸会话并将其延长5分钟。请求结束时,您还可以触摸会话并将其延长1分钟,然后再释放锁定。如果“结束请求+一分钟”的结果早于“开始请求+ 5分钟”,则使用后者作为超时;否则使用前者。 (当然,5分钟和1分钟可能是你喜欢的任何价值。)
我想知道你正在使用什么样的“缓存”。根据您的描述,似乎缓存会“自动”销毁会话对象。如果是这种情况,那么当请求到达时,您可以 touch
具有非常大的超时值的会话,例如一天。请求结束后,您重新touch
使用合理的值,例如 5分钟。或者, smarter ,使用值(5 minutes - request_time > 1 minute) ? (5 minutes - request_time) : 1 minute)
,其中request_time
是请求所花费的时间。
希望这有帮助。
Asuka Kenji(来自香港)
答案 1 :(得分:1)
首先,我不会在Cache中做任何与Session相关的事情。如果会话需要自杀,如果没有使用这么多分钟,我会在Session中跟踪所有这些。其次,我倾向于使用一个包装类来访问Session,这样当访问或触摸任何值时,标记(它本身可以存储在Session中)来确定它是否应该自杀以及代码可以封装“杀死会话”。