我们最近从Tomcat 4迁移了一个大型,高需求的Web应用程序到Tomcat 5.5,并注意到一些特殊的减速行为似乎与JVM暂停有关。为了在Tomcat 4上运行我们的应用程序并支持随着时间的推移增加的负载,许多不那么标准的JVM参数按照下面的设置和调整,我希望有Tomcat JVM调优经验的人可以评论任何可能有害的东西到Tomcat 5.5安装。还要注意其中一些可以从以前版本的Java继承(我们在Java 1.6上运行Tomcat 4并且这些参数成功运行了一段时间,但是可能已经引入了一些来帮助Java 1.4上的垃圾收集,这是我们的Tomcat 4安装了很长时间,现在可能弊大于利了。
一些说明:
- 应用程序内存占用量
大约1GB,可能稍微超过。
- CPU不是问题 - 所有机器
服务应用程序(负载平衡)是
CPU低于30%
- 机器上的物理内存有很多空间。
- -XX:MaxPermSize = 512m是作为5.5升级的一部分添加的唯一参数,并且是对outofmemory permgen空间问题(它解决了)的反应。
- 在Java 1.6,Solaris OS上运行
-server -Xms1280m -Xmx1280m -XX:MaxPermSize = 512m -XX:ParallelGCThreads = 20 -XX:+ UseConcMarkSweepGC -XX:+ UseParNewGC -XX:SurvivorRatio = 8 -XX:TargetSurvivorRatio = 75 -XX:MaxTenuringThreshold = 0 -XX:+ AggressiveOpts -XX:+ PrintGCDetails -XX:+ PrintGCTimeStamps -XX:-TraceClassUnloading -Dsun.io.useCanonCaches = false -Dsun.net.client.defaultConnectTimeout = 60000 -Dsun.net.client.defaultReadTimeout = 60000
其中一位Java冠军,Kirk Pepperdine的博客: http://kirk.blog-city.com/how_to_cripple_gc_ergonomics.htm。
引用1
“GC文档会告诉你设置会产生什么影响,但通常不知道效果会是什么。你在路上走错路的最大线索是你明确设置一个值然后给出GC人体工程学的提示。另一个线索是,如果你没有合理的理由调整设置。只是因为一些所谓的专家说这种设置效果最好的只是噪音,而不是声音,而且不是理由。“
引用2
“正如我在一篇热门的博客文章中所说的那样,除非你有充分的理由这样做,否则不要触摸旋钮。如果你必须触摸旋钮,只需使用那些有助于人体工程学而不是那些针脚的那些旋转减少人体工程学的能力,以满足您的暂停时间和吞吐量目标。“
所以,我建议你回到平原
-server -Xms1280m -Xmx1280m -XX:MaxPermSize = 512m -XX:+ UseConcMarkSweepGC -XX:+ PrintGCDetails -XX:+ PrintGCTimeStamps -XX:-TraceClassUnloading -Dsun.io.useCanonCaches = false -Dsun.net.client.defaultConnectTimeout = 60000 -Dsun.net.client.defaultReadTimeout = 60000
找出是否能提供更好的性能。如果是的话,坚持下去
BTW,-XX:MaxPermSize = 378m有什么问题吗?
Java 1.6具有比1.4更好的人机工程学。您可能希望将其调整为小于1.4
顺便说一句,你尝试过Tomcat 6吗? Tomcat 6在Java 6上运行得比Tomcat 5.5好得多。
P.S:我现在已经使用Tomcat了一段时间,并且通常尝试给予sun的JDK免费统治,在这里和那里进行一些调整。
其中一位Java冠军,Kirk Pepperdine的博客: http://kirk.blog-city.com/how_to_cripple_gc_ergonomics.htm。
引用1
“GC文档会告诉你设置会产生什么影响,但通常不知道效果会是什么。你在路上走错路的最大线索是你明确设置一个值然后给出GC人体工程学的提示。另一个线索是,如果你没有合理的理由调整设置。只是因为一些所谓的专家说这种设置效果最好的只是噪音,而不是声音,而且不是理由。“
引用2
“正如我在一篇热门的博客文章中所说的那样,除非你有充分的理由这样做,否则不要触摸旋钮。如果你必须触摸旋钮,只需使用那些有助于人体工程学而不是那些针脚的那些旋转减少人体工程学的能力,以满足您的暂停时间和吞吐量目标。“
所以,我建议你回到平原
-server -Xms1280m -Xmx1280m -XX:MaxPermSize = 512m -XX:+ UseConcMarkSweepGC -XX:+ PrintGCDetails -XX:+ PrintGCTimeStamps -XX:-TraceClassUnloading -Dsun.io.useCanonCaches = false -Dsun.net.client.defaultConnectTimeout = 60000 -Dsun.net.client.defaultReadTimeout = 60000
找出是否能提供更好的性能。如果是的话,坚持下去
BTW,-XX:MaxPermSize = 378m有什么问题吗?
Java 1.6具有比1.4更好的人机工程学。您可能希望将其调整为小于1.4
顺便说一句,你尝试过Tomcat 6吗? Tomcat 6在Java 6上运行得比Tomcat 5.5好得多。
P.S:我现在已经使用Tomcat了一段时间,并且通常尝试给予sun的JDK免费统治,在这里和那里进行一些调整。
作为一个正在处理这个问题的人,我当然没有任何确定的答案,特别是考虑到特定于应用程序的这类事情。您可能会看到一个很好的参考资料:
http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html
但是,它是一个相当长的jvm参数列表,这表明可能有不必要的参数设置,特别是考虑到你有几个调试选项(PrintGCDetails,PrintGCTimeStamps,TraceClassUnloading),这对生产应用程序来说不是很好。 60秒的超时也可能会占用资源。 “服务器”是默认值,但不会造成任何伤害。
应用程序如何以最小的调整参数(jvm size,MaxPermSize)运行?
您可能还想查看更改Tomcat将用于处理请求的最小/最大线程数 conf/server.xml
:
<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" ...
我在之前的工作中听到的一条经验法则是maxThreads应该等于您希望处理的同时连接数量。我不确定这种说法有多科学,虽然我当然认为这是有道理的,因为你不希望客户被阻止等待线程释放来处理他们的请求。
也可能值得尝试使用替代JVM(如JRockit)来查看垃圾收集模型中的差异是否适合您的应用程序。