Tomcat的webapps吃了所有的内存

我正在运行一些tomcat服务器,我们部署了我们的编码器编写和实现的应用程序。 问题在于,在我们的一些服务器中,尤其是那些有多个请求的服务器,内存变得非常快速,服务器开始performance不佳。 我是新来的这个angular色,我的前任提到,这是由于应用程序中的代码没有被正确写入,它把所有的内存都logging下来了……这是公平的,但是我想知道是否有任何事情可以做减轻或消除这个目前的解决scheme,直到代码被改进是多周的tomcat重启,这在我看来感觉像是一个矫枉过正的! (没有双关语意)

下面是在tomcat需要被杀死和重新启动之前的htop的输出(这是另一件事,大多数时候tomcat不能被要求礼貌地退出,你必须杀死它-9,不知道这是否正常)

我查了一些资源,但没有find具体的东西可以排除我的问题,所以任何好的专业知识都会受到欢迎!

我已经包含了一张图片,你可以看到这个过程似乎重复了好几次,但是并没有像一些人所说的那样使用超过300个的记忆体,而只有7个演出,并不完全确定这意味着什么。

其实这可能是一个问题,如果你做ps你只能看到下面的过程:

root 5215 3.4 64.8 8310716 5301436 ? Sl Nov04 146:25 /usr/bin/java -Djava.util.logging.config.file=/opt/tomcat/conf/logging.properties -Djava.awt.headless=true -Xms5G -Xmx5G -XX:PermSize=512m -XX:MaxPermSize=512m -XX:NewSize=1G -XX:MaxNewSize=1G -Duser.langua

无论如何回到我的观点,它太重载了太容易,任何方式来防止这个在Tomcat版本7.0.28?

这是server.xml

 <?xml version='1.0' encoding='utf-8'?> <Server port="8105" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.core.JasperListener" /> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <GlobalNamingResources> <Environment name="databasePlaceHolder" type="java.lang.String" value="com_xxx_yyy_au"/> <Environment name="com.xxx.databasename" type="java.lang.String" value="com_xxx_yyy_au"/> <Environment name="com.xxx.JMS.url" type="java.lang.String" value="tcp://localhost:61616"/> <Environment name="remoteServerURL" type="java.lang.String" value="https://yyy.xxx.com/"/> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <Service name="Catalina"> <Connector port="8109" protocol="AJP/1.3" redirectPort="0443" /> <Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" /> </Host> </Engine> </Service> </Server> 

这是setenv.sh文件的内容:

JAVA_OPTS =“ – Djava.awt.headless = true -Xms5G -Xmx5G -XX:PermSize = 512m -XX:MaxPermSize = 512m -XX:NewSize = 1G -XX:MaxNewSize = 1G -Duser.language = en -Duser.region = GB”

JAVA_OPTS =“$ {JAVA_OPTS} -XX:+ UseParallelGC -XX:+ PrintGCDetails -XX:+ PrintGCDateStamps -XX:+ PrintTenuringDistribution”

这是htop输出,可能是错误的

至于htop是错误的,我认为你已经启用线程信息,所以你看到每个Java条目是一个线程相同的过程。 要validation此切换“显示线程”(按“H”切换)。

从htop屏幕截图我注意到你的服务器有8G的RAM,所以如果你把JVM限制在5G + PermGen +一些开销,你应该没问题,假设没有其他内存饥饿的进程在运行。

接下来要检查的是垃圾收集器,根据你的java版本,有一个标志(至less在oracle java / openjdk中)使JVMlogging每个GC事件,通常是: -verbose:gc -XX:+PrintGCDateStamps -Xloggc:SOMEFILENAME并检查甚至增加的GC活动,如果发生内存泄漏,您将看到垃圾收集变得更频繁,因为时间经过,直到它使用所有的CPU试图释放内存没有成功,并且你可以得到内存不足的exception你的日志。 在这一点上,你必须kill -9你的应用程序的问题。 但是现在你将有一个validationGC活动的日志来certificate有没有内存泄漏。

接下来,如果您部署了多个应用程序,请尝试在可能的情况下将应用程序分别放在一个tomcat实例中。 或者在内存不足时启用堆转储。

至于做什么而没有固定代码的可能性,那么假设有内存韭菜设置GC频率监视,例如,如果在一分钟内有3个完整的GC尝试,自动重新启动tomcat。

丑陋的,但如果没有其他select,它可以让你在晚上睡觉。

由于我没有看到完整的命令行参数用于启动JVM,并且不知道您在那里部署的应用程序的性质,所以我只能猜测您的应用程序正在创build大量“长寿命”的对象, oldgen空间,你在那里的内存不足。 此外,oldgen空间中的GC收集相当昂贵,可能您的JVM在某些时候无法跟上GC运行并陷入停顿。

话虽如此,我可以build议下面的JVM调优参数。

删除下面的两个:

 -XX:NewSize=1G -XX:MaxNewSize=1G 

并添加以下内容:

 -XX:+UseParallelOldGC -XX:SurvivorRatio=10 -XX:NewRatio=2 

如果问题没有解决,继续增加NewRatio到3,4,5,看看JVM什么时候足够稳定,可以继续运行,没有任何问题。 另外,我不知道为什么你需要512M的permgen大小,例如-XX:PermSize=512m 。 与您的应用程序开发人员检查,看看他们真的需要这么多,如果可能的话减less它。

另外,当问题发生时,在杀死进程之前,运行以下代码并在这里发布输出,以便为尝试帮助你的人提供线索。 (注意:你必须以root身份运行)。

 jmap -heap <pid_of_jvm> 

PS:由@Fredi解释的htop输出是正确的,误导性地将LWP线程ID标记为PID。