servlet规范没有提及任何有关内存注意事项的内容,因此您将无法获得帮助.
除非专门配置,否则Tomcat将允许您使用HttpSession对象(实际上,它们的内容)使用所有可用内存,最终JVM将开始抛出OutOfMemoryErrors,可能会导致服务器停机(尽管JVM将继续运行)很多事情会表现得……不可预测且不幸的是.
如果单个请求开始在局部变量等中使用大量内存,则请求处理线程将遭受OutOfMemoryError并停止处理当前请求. (我相信在这种情况下,请求处理线程实际上将由Tomcat请求处理线程池回收).垃圾收集器很可能在此后不久运行并重新声明该请求使用的内存,您的服务器将稳定下来.
另一方面,如果您占用大量内存并将这些对象存储到用户的HttpSession中,那么GC无法释放任何内存,您的服务器将不断受到OutOfMemoryErrors的影响.虽然Tomcat将按指定的时间表到期(默认是在30分钟不活动之后),但是会话清理线程在操作期间可能会遇到OutOfMemoryError,因此无法履行其职责,使整个情况更加复杂(因为,实际上,HttpSessions将会永不过期).
有几种方法可以缓解上述不幸的情况.哪一个对您有意义取决于您的要求和环境.
>增加堆大小.这显然只会让你到目前为止.如果你用HttpSession和相关对象填充16GiB堆,那么你就达到了商品硬件的极限,你不能简单地买一个更大的盒子.
>减少会话到期时间(默认为30分钟).如果未明确终止会话(例如,通过注销功能),则HttpSession对象及其所有内容将一直存在,直到过期时间间隔过去.如果您在很多被遗弃的会话中有大量数据,减少会话到期时间可能会给您一些喘息空间.
>停止将大量数据放入用户的HttpSession中.虽然这看起来像是一个令人讨厌的建议(“停止这样做”),但老实说这是一个有效的建议:你真的需要在会话中存储这么多东西吗?如何使用某种数据存储(关系数据库,非关系型数据库,如Cassandra,webcache等)?也许将数据存储在磁盘上的文件中?虽然这些建议肯定会限制您快速访问数据的能力,但它们肯定是比您的服务器在会话中如此多的重量下崩溃更好的选择.
>使用Tomcat的PersistentManager,它是一个会话管理器,能够将活动(但空闲)会话交换到某些外部存储(默认情况下可以使用基于文件和基于JDBC的存储机制).这可以让你在很长的路要走,同时找出一些其他的地方把你所有的数据放到用户的会话中.
除#4以外的所有容器都适用于任何servlet容器. #4应该可供JBoss用户使用,因为JBoss在内部使用Tomcat.对于其他容器,您可能会发现存在类似的功能.