生产服务器上的 Tomcat、PermGen 和重新部署
Posted
技术标签:
【中文标题】生产服务器上的 Tomcat、PermGen 和重新部署【英文标题】:Tomcat on production server, PermGen and redeploys 【发布时间】:2011-04-01 01:53:08 【问题描述】:看起来像
MemoryError: PermGen space
java.lang.OutOfMemoryError: PermGen space
是一个常见的问题。您可以增加 perm 空间的大小,但在 100 或 200 次重新部署后它将被填满。跟踪 ClassLoader 内存泄漏几乎是不可能的。
您在生产服务器上使用 Tomcat(或另一个简单的 servlet 容器 - Jetty?)的方法是什么?每次部署解决方案后是否重新启动服务器?
您是否将一个 Tomcat 用于多个应用程序?
也许我应该在不同的端口(或嵌入式 Jetty)上使用多个 Jetty 服务器,并且每次都取消部署/重新启动/部署?
【问题讨论】:
你试过增加堆大小吗? 不是堆大小问题,而是类字节码卸载问题。他们说类没有在 JVM 中卸载,PermGen 空间没有被清扫。 【参考方案1】:我放弃了使用 tomcat 管理器,现在总是关闭 tomcat 重新部署。
我们在同一台服务器上运行两个 tomcat,并使用带有 mod_proxy_ajp 的 apache webserver,因此用户可以通过同一个端口 80 访问这两个应用程序。这也很好,因为当 tomcat 关闭时,用户会看到 apache Service Unavailable 页面。
【讨论】:
我们在HAProxy后面的不同端口上使用两个tomcat来提供蓝绿部署方案。当“Green”启动并运行时,“Blue”服务器关闭,HAProxy 然后切换到“Green”。然后下一次部署转到“蓝色”。【参考方案2】:您可以尝试添加这些 Java 选项:
-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
这会在 PermGen 空间中启用垃圾收集(默认关闭)并允许 GC 卸载类。此外,您应该使用其他地方提到的 -XX:PermSize=64m -XX:MaxPermSize=128m 来增加可用 PermGen 的数量。
【讨论】:
这些应该如何提供帮助?【参考方案3】:确实,这是个问题。我们在 Tomcat 服务器上运行三个 Web 应用程序:第 1 个使用 Web 应用程序框架、Hibernate 和许多其他 JAR,第 1 个使用 Web 应用程序框架。 2 使用 Hibernate 和一些 JAR 并且没有。 3基本上是一个非常简单的JSP应用程序。
当我们部署没有。 1、我们总是重启Tomcat。否则 PermGen 空间错误很快就会给我们带来麻烦。 2 号有时可以毫无问题地部署,但因为它经常在没有时发生变化。 1 也一样,无论如何都会安排重启。 No. 3 完全没有问题,可以根据需要随时部署而不会出现问题。
所以,是的,我们通常重启 Tomcat。但我们也很期待 Tomcat 7,它应该能够处理许多隐藏在不同第三方 JAR 和框架中的内存/类加载器问题。
【讨论】:
【参考方案4】:HotSpot 中的 PermGen 切换只会延迟问题,最终还是会得到 OutOfMemoryError。
这个问题我们已经有很长时间了,到目前为止我找到的唯一解决方案是使用 JRockit。它没有 PermGen,所以问题就消失了。我们现在正在我们的测试服务器上对其进行评估,自从切换以来我们还没有遇到过 PermGen 问题。我还尝试在我的本地机器上重新部署超过 20 次,使用的应用程序在第一次重新部署时出现此错误,并且一切顺利。
JRockit 是为了集成到 OpenJDK 中,所以这个问题可能会在未来的 Java 中消失。
http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html
而且它是免费的,与 HotSpot 使用相同的许可:
https://blogs.oracle.com/henrik/entry/jrockit_is_now_free_and
【讨论】:
我认为 JRockit 将类定义保留在堆上。每次重新部署后堆不会增长吗? “JRockit Mission Control”对堆大小有何影响? 据我所见,每次重新部署后堆都保持相同的大小。我现在再次尝试了大约 10 次重新部署。【参考方案5】:您应该启用 PermGen 垃圾回收。默认情况下,Hotspot VM 不会收集 PermGen 垃圾,这意味着所有加载的类文件都永远保留在内存中。每个新部署都会加载一组新的类文件,这意味着您最终会用完 PermGen 空间。
【讨论】:
正如@Soundlink所说,在PermGen中开启GC的参数是“-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled”。在 Ubuntu 上,您可以将这些添加到 /etc/default/tomcat6 中的 JAVA_OPTS。【参考方案6】:您使用的是哪个版本的 Tomcat? Tomcat 7 和 6.0.30 有许多功能可以避免这些泄漏,或者至少会警告您它们的原因。
This presentation 的 SpringSource 的 Mark Thomas(和长期的 Tomcat 提交者)在这个主题上非常有趣。
【讨论】:
这个问题是在 2010 年提出的。当时 Tomcat 7 正在计划中。我们的解决方案是关闭tomcat,将旧WAR 复制到备份目录,从Hudson 下载新WAR,启动Tomcat 的应用程序。我们使用两个 tomcat 和蓝绿部署模式。【参考方案7】:仅供参考,有一个新版本的Plumbr 工具,也可以监控和检测永久代泄漏。
【讨论】:
以上是关于生产服务器上的 Tomcat、PermGen 和重新部署的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat Java.OutOfMemoryError : PermGen Space异常
windows系统bat方式启动tomcat出现java.lang.OutOfmemoryError:PermGen Space 错误