java - 当并发 session 过多时,Java Web 容器的内存会发生什么变化?

标签 java tomcat webserver

今天工作中遇到一个问题:

假设我有很多并发用户访问我的网站,每个用户都有自己的数据存储在用户 session 中。考虑到我的 JVM 中可用内存量有限,当并发 Activity session 达到容器 JVM 内存不足的程度时会发生什么或应该发生什么?

我试图在 servlet 规范中找到关于应该发生什么的内容,但那里没有确定的内容,它只是说开发人员将有权访问 session 对象等。这让我认为它必须是特定于提供者的。

以 Tomcat 为例,Web 服务器是否刚开始抛出 OutOfMemoryException?或者它处理这个问题的方式更聪明,例如将 session 分页到另一个缓存?还是另一种方式?

最佳答案

servlet 规范没有说明任何关于内存注意事项的内容,因此您在那里得不到任何帮助。

除非特别配置,否则 Tomcat 将允许您使用 HttpSession 对象(实际上是它们的内容)耗尽所有可用内存,最终 JVM 将开始抛出 OutOfMemoryError,可能会占用你的服务器宕机了(虽然 JVM 会继续运行,但很多事情会表现得......不可预测和不幸)。

如果单个请求开始在局部变量等中使用大量内存,请求处理线程将遭受 OutOfMemoryError 并停止处理当前请求。 (我相信在这种情况下,请求处理线程实际上会被 Tomcat 请求处理线程池回收)。垃圾收集器可能会在此后不久运行并回收该请求使用的内存,您的服务器将稳定下来。

另一方面,如果您用完大量内存并将这些对象存储到用户的 HttpSession 中,那么 GC 将无法释放任何内存,您的服务器将不断遭受 OutOfMemoryError。尽管 Tomcat 会按指定的时间表(默认为 30 分钟不活动后)使 session 过期,但 session 清理线程可能会在操作期间遇到 OutOfMemoryError,因此无法履行其职责,从而使整个情况更加复杂(因为实际上,HttpSession 永远不会过期)。

有几种方法可以减轻上述不幸的情况。哪一个对您有意义取决于您的要求和环境。

  1. 增加堆大小。这显然只会让你走到这一步。如果您用 HttpSession 和相关对象填充 16GiB 堆,那么您将达到商品硬件的极限,您不能简单地购买更大的盒子。

  2. 缩短 session 过期时间(默认为 30 分钟)。如果 session 未明确终止(例如,通过注销功能),则 HttpSession 对象及其所有内容会一直存在,直到过期间隔结束。如果您在大量放弃的 session 中有大量数据,减少 session 过期时间可能会给您一些喘息的空间。

  3. 停止向用户的 HttpSession 中放入如此多的数据。虽然这似乎是一个令人讨厌的建议(“停止那样做”),但它确实是一个有效的建议:您真的需要在 session 本身中存储这么多东西吗?使用某种数据存储(关系数据库、非关系数据库,如 Cassandra、网络缓存等)怎么样?也许将数据存储在磁盘上的文件中?虽然这些建议肯定会限制您快速访问数据的能力,但它们肯定比让您的服务器在您的 session 中因太多内容而崩溃更好的选择。

    <
  4. 使用 Tomcat 的 PersistentManager ,这是一个 session 管理器,能够将 Activity (但空闲) session 交换到某些外部存储(默认情况下基于文件和基于 JDBC 的存储机制可用)。当您找到其他地方将您推送到用户 session 中的所有数据放入用户 session 时,这可以让您走得更远。

除#4 之外的所有内容都适用于任何 servlet 容器。 #4 应该对 JBoss 用户可用,因为 JBoss 在内部使用 Tomcat。对于其他容器,您可能会发现存在类似的功能。

关于java - 当并发 session 过多时,Java Web 容器的内存会发生什么变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11956038/

相关文章:

java - 类构造函数参数导致异常

apache - 如何重定向页面并隐藏其网址?

java - gson - 如何比较 JsonObjects 忽略几个节点?

java - 将 JCheckBox 添加到列中除最后一个单元格之外的所有单元格

tomcat - 在命令提示符下使用 Java Servlet

java - RSA secret 预主错误

webserver - auto_prepend_file 多个文件

C Web 服务器 - 打印传入数据?

java - 使用 guice 将 CrossOriginFilter 添加到 dropwizard

java - Hibernate物化 View ,嵌入两个Entity?