HttpSession中的信息太多了

ble*_*esd 4 java session servlets

你好,你怎么看待这个问题?

我们确实有太多的信息HttpSession,因为计算了大量信息,最终需要在请求之间存储一些大的对象图.

是否适合使用memcache等任何缓存?或者它与增加JVM的内存相同?

担心在请求之间将其存储在数据库中.如果我们收到OutOfMemory错误,你会用什么?

谢谢.

KLE*_*KLE 7

我认为真正的重点是数据的生命周期.


想想HttpSession的这两个特征:

  • 集群中时,容器负责复制 HttpSession.这很好(你不必自己管理),但如果这会导致太多的交换,那么在性能方面可能会很危险......如果你的应用程序没有聚集,那么就忘了这一点.
  • HttpSession 的生命周期可能是几分钟或几个小时,也就是用户保持活动状态.这非常适合具有生命周期的信息(连接信息,首选项,授权......).但它不适合从一个屏幕到下一个屏幕有用的数据,我们称之为瞬态+数据.

如果您有群集需求,数据库会负责处理它.但要注意,你不能在内存中缓存任何内容.

存储在数据库中的寿命甚至更长(在会话之间持续存在,甚至在重新启动之间!),因此问题甚至是值得的(除了为性能问题交换内存问题).

我认为这对于预计寿命不会持续的数据来说是错误的方法......


瞬态数据

如果数据仅对一个请求有用,那么它通常存储在HttpRequest中,没问题.

但是如果它被用于一些请求(一个屏幕内的交互,或者像助手那样的屏幕序列......),HttpRequest太短而无法存储它,但是HttpSession太长了.需要定期清理数据.

在HttpSession中很多内存问题都涉及到这样的数据是短暂的,但没有被清除(在全忘了,还是没有清理异常时,或者当用户不尊重规则的流程:点击Back,使用一个书签, clic在不同的菜单或其他).

缓存库以获得正确的生命周期

为了完全避免这种清理工作(并避免出现问题时OutOfMemory的风险),您可以将信息存储在具有正确生命周期的数据结构中.由于容器没有提供此功能(无论如何都与应用程序相关),您需要使用缓存库(如上所述;我们使用EhCache)自行实现.

这个想法是你有一个技术代码(与一个功能页面无关,但是全局实现,例如使用ServletFilter ......),确保在不再需要对象之后总是进行清理.

您可以使用以下策略中的一个(或多个)来清理缓存来设计此缓存.每个与功能寿命相关的政策:

  • 对于仅与一个屏幕相关的数据(但有几个请求:重新加载屏幕,Ajax请求......),缓存一次只能存储一个屏幕的数据(对于每个会话),称之为"currentScreenCache".这保证了,如果用户进入另一个屏幕(即使是以非托管方式),新屏幕将覆盖"currentScreenCache"信息,并且可以对先前信息进行垃圾收集.

实现思路:每个请求必须携带其screenId,负责清除缓存的技术代码检测当前的HttpSession id当前screenId与缓存中的那个不匹配的时间.然后它清除或重置缓存中的该项.

  • 对于仅用于一系列连接屏幕的数据(称之为功能模块),同样适用于模块级别.

实现:和以前一样,每个请求都必须携带模块ID ...

  • 对于重新计算成本高昂的数据,缓存库可以配置为存储最后的X个计算值(之前的那些被认为不太可能在不久的将来有用).在典型的使用中,会定期询问相同的内容,因此您有许多缓存命中.在密集使用时,达到X限制并且内存不会膨胀,从而防止OutOfMemory错误(以下次重新计算为代价).

实现:缓存库原生支持这个限制因素,还有几个......

  • 对于仅有效几分钟的数据,缓存库可以原生配置为在该延迟后丢弃它...

  • ......还有更多,请参阅缓存库配置以了解其他想法.

注意:每个缓存可以是应用程序范围的,或特定于用户,HttpSession ID,公司ID或其他功能值...